[SDOI2010]大陸爭霸
阿新 • • 發佈:2018-08-24
href putchar 優先隊列 view while 圖片 tdi lan closed
嘟嘟嘟
首先可以知道,對於在哪個時候攻占一個城市,應該是他的最短到達時間和最早進入時間的最大值(max(d1[i], d2[i]))。
最短到達時間:就是樸素的最短路d1[i]。
最早進入時間:設所有到達有他的結界發生器的城市為j,那麽應該是在所有最短時間中取max,作為d2[i]。
於是就可以用dijkstra寫了。
每一次成功更新節點 i 的d1時,就更新所有 i 能控制的節點 j 的d2。
我們還要記錄每一個節點的入度,代表控制它的城市有幾個,然後如果他的d2被更新了一次,就減1,若果為0,就代表所有控制他的城市都已經處理完了,於是就可以吧這個城市加入優先隊列中,參與dijkstra。
最後的答案就是 max(d1[n], d2[n])。
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #include<cstdlib> 7 #include<vector> 8 #include<queue> 9 #include<stack> 10 #include<cctype> 11 usingView Codenamespace std; 12 #define enter puts("") 13 #define space putchar(‘ ‘) 14 #define Mem(a) memset(a, 0, sizeof(a)) 15 typedef long long ll; 16 typedef double db; 17 const int INF = 0x3f3f3f3f; 18 const db eps = 1e-8; 19 const int maxn = 3e3 + 5; 20 inline ll read() 21 { 22 ll ans = 0; 23 char ch = getchar(), last = ‘‘; 24 while(!isdigit(ch)) last = ch, ch = getchar(); 25 while(isdigit(ch)) ans = (ans << 3) + (ans << 1) + ch - ‘0‘, ch = getchar(); 26 if(last == ‘-‘) ans = -ans; 27 return ans; 28 } 29 inline void write(ll x) 30 { 31 if(x < 0) putchar(‘-‘), x = -x; 32 if(x >= 10) write(x / 10); 33 putchar(x % 10 + ‘0‘); 34 } 35 36 int n, m; 37 vector<int> v[maxn],c[maxn], su[maxn]; //su[i]代表有哪些城市控制城市i 38 int cnt[maxn]; //記錄入度 39 40 #define pr pair<int, int> 41 #define mp make_pair 42 int d1[maxn], d2[maxn]; 43 bool in[maxn]; 44 void dijkstra(int s) 45 { 46 for(int i = 1; i <= n; ++i) d1[i] = INF; 47 d1[s] = 0; 48 priority_queue<pr, vector<pr>, greater<pr> > q; 49 q.push(mp(d1[s], s)); 50 while(!q.empty()) 51 { 52 pr node = q.top(); q.pop(); 53 int now = node.second, dis = node.first; 54 if(in[now]) continue; 55 in[now] = 1; 56 for(int i = 0; i < (int)v[now].size(); ++i) 57 { 58 if(dis + c[now][i] < d1[v[now][i]]) 59 { 60 d1[v[now][i]] = dis + c[now][i]; 61 if(!cnt[v[now][i]]) q.push(mp(max(d1[v[now][i]], d2[v[now][i]]), v[now][i])); 62 //只有入度為0的節點才可以被加入隊列 63 } 64 } 65 for(int i = 0; i < (int)su[now].size(); ++i) 66 { 67 cnt[su[now][i]]--; 68 // d2[su[now][i]] = max(d2[su[now][i]], dis); 69 if(!cnt[su[now][i]]) 70 { 71 d2[su[now][i]] = dis; 72 // 這句話和68句話是等價的,因為最後一個到達控制它的城市時間一定是最長的 73 q.push(mp(max(d1[su[now][i]], d2[su[now][i]]), su[now][i])); 74 } 75 } 76 } 77 write(max(d1[n], d2[n])); 78 } 79 80 int main() 81 { 82 n = read(); m = read(); 83 for(int i = 1; i <= m; ++i) 84 { 85 int x = read(), y = read(), w = read(); 86 v[x].push_back(y); c[x].push_back(w); 87 } 88 for(int i = 1; i <= n; ++i) 89 { 90 cnt[i] = read(); 91 for(int j = 1; j <= cnt[i]; ++j) su[read()].push_back(i); 92 } 93 dijkstra(1); 94 return 0; 95 }
[SDOI2010]大陸爭霸