【spfa】假期计划(jzoj 3936)
生活随笔
收集整理的這篇文章主要介紹了
【spfa】假期计划(jzoj 3936)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
假期計劃
jzoj 3936
題目大意
給你一個有向圖(n,m?20000n,m\leqslant 20000n,m?20000),現在有一些作為樞紐的點,且保證每一條邊的兩個點至少有一個是樞紐點,現在給q個詢問,問某一個點到另一個點的最短路,你只需輸出可以到達的數量,和可以到達的最短路之和
輸入樣例
3 3 1 2 1 2 10 2 3 10 2 1 5 2 1 3 3 1輸出樣例
1 20數據范圍
對于 30%的數據,N?100,M?2,000。N\leqslant 100,M\leqslant 2,000。N?100,M?2,000。
對于 100%的數據,1?N,M?20,000,1?K?200,1?Q?50,000,1?di?10,000。1\leqslant N,M\leqslant 20,000,1\leqslant K\leqslant 200,1\leqslant Q\leqslant 50,000, 1\leqslant d_i\leqslant 10,000。1?N,M?20,000,1?K?200,1?Q?50,000,1?di??10,000。
樣例說明
對于第一個航班,唯一可行的路線是1?>2?>31->2->31?>2?>3,花費 20。
解題思路
因為樞紐點很少,我們對于每一個樞紐點跑一邊spfaspfaspfa
如果詢問的出發點是樞紐點,那就是直接最短路的值
如果不是,那和他相連的就都是,然后計算這條邊加和他相連的點到終點的最短路就是結果
代碼
#include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long using namespace std; ll n, m, k, q, x, y, z, tot, num, sum, ans, p[20010], v[20010], head[20010], b[210][20010]; struct rec {ll to, l, next; }a[20010]; void spfa(ll x) {memset(b[v[x]], 127/3, sizeof(b[v[x]]));b[v[x]][x] = 0;//以第x個樞紐為起點到各個點的最短路p[x] = 1;queue<ll>d;d.push(x);while(!d.empty()){ll h = d.front();d.pop();for (ll i = head[h]; i; i = a[i].next)if (b[v[x]][h] + a[i].l < b[v[x]][a[i].to]){b[v[x]][a[i].to] = b[v[x]][h] + a[i].l;if (!p[a[i].to]){p[a[i].to] = 1;d.push(a[i].to);}}p[h] = 0;} } int main() {scanf("%lld%lld%lld%lld", &n, &m, &k, &q);for (ll i = 1; i <= m; ++i){scanf("%lld%lld%lld", &x, &y, &z);a[++tot].to = y;a[tot].l = z;a[tot].next = head[x];head[x] = tot;}for (ll i = 1; i <= k; ++i){scanf("%lld", &x);v[x] = i;//記錄下他是第幾個,方便減小內存spfa(x);}for (ll i = 1; i <= q; ++i){scanf("%lld%lld", &x, &y);sum = 200000010;if (v[x]) sum = min(sum, b[v[x]][y]);//他就是樞紐for (ll j = head[x]; j; j = a[j].next)if (v[a[j].to])sum = min(sum, a[j].l + b[v[a[j].to]][y]);//相連的樞紐if (sum <= 200000000){num++;ans += sum;}}printf("%lld\n%lld", num ,ans);return 0; }總結
以上是生活随笔為你收集整理的【spfa】假期计划(jzoj 3936)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 云顶霞的装备怎么出 霞的出装
- 下一篇: IQ测试(jzoj 5048)