1. 程式人生 > >[SDOI2010]大陸爭霸

[SDOI2010]大陸爭霸

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 using
namespace 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 }
View Code

[SDOI2010]大陸爭霸