1. 程式人生 > >【tarjan縮點+分層圖】草鑑定Grass Cownoisseur

【tarjan縮點+分層圖】草鑑定Grass Cownoisseur

P3119 [USACO15JAN] 草鑑定Grass Cownoisseur

tarjan縮點+建分層圖

縮點:單向邊+可重複走一個牧場

縮完點後, 對於不在原圖中的一條邊(u, v),  if(sd[u] != sd[v]) 連邊, 建立新圖編號為1~tot//sd[] 該點屬於哪個強連通分量, tot是強連通的數量

分層圖:可逆向走一次,分層圖頂點編號為 tot+1 ~ 2 * n;對於縮點後新圖中的一條邊(u, v), 將該邊終點與分層圖的起點連邊, 達到逆向走一次的目的add(v, u+tot)

分層圖自身也要連邊, 對於縮點後的新圖(u, v) , 分層圖連相應的邊add(u+tot, v+tot)

記得分層圖上的點權值與縮點後新圖權值相同!!

因為最後會走回1號點,會加上1號點所在強連通的權值, 所以開始初始dis只可以為0

自信程式碼奼紫嫣紅竟因忘刪註釋?!陣列開的正好re兩個點, 開大十倍就好了QAQ

 1 #include<queue>
 2 #include<cstdio>
 3 #include<iostream>
 4 using namespace std;
 5 const int sz = 1000010;
 6 int n, m, tim = 0, top = 0, num = 0, num2 = 0, tot = 0;
 7
int h[sz], dfn[sz], low[sz], sta[sz], x[sz], y[sz], sd[sz]; 8 int h2[sz], dis[sz ], node[sz]; 9 bool vis[sz], book[sz ]; 10 struct Egde { 11 int nxt, to, dis; 12 }e[sz], e2[sz << 1]; 13 int read() { 14 char ch = getchar(); int x = 0, f = 1; 15 while(ch < '0' || ch > '
9') {if(ch == '-') f = -1; ch = getchar();} 16 while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();} 17 return x * f; 18 } 19 void add(int from, int to) { 20 e[++num].nxt = h[from]; 21 e[num].to = to; 22 h[from] = num; 23 } 24 void add2(int from, int to) { 25 e2[++num2].nxt = h2[from]; 26 e2[num2].to = to; 27 h2[from] = num2; 28 } 29 void tarjan(int u) { 30 low[u] = dfn[u] = ++tim; 31 sta[++top] = u; 32 vis[u] = 1; 33 for(int i = h[u]; i; i = e[i].nxt) { 34 int v = e[i].to; 35 if(!dfn[v]) { 36 tarjan(v); 37 low[u] = min(low[v], low[u]); 38 } 39 else if(vis[v]) low[u] = min(low[u], dfn[v]); 40 } 41 if(dfn[u] == low[u]) { 42 tot++; 43 while(u != sta[top+1]) { 44 sd[sta[top]] = tot; 45 node[tot]++; 46 vis[sta[top]] = 0; 47 top--; 48 } 49 } 50 } 51 void spfa(int s) { 52 queue<int>q; 53 for(int i = 1; i <= (n<<1); i++) { 54 dis[i] = 0; 55 book[i] = 0; 56 } 57 book[s] = 1; 58 q.push(s); 59 while(!q.empty()) { 60 int u = q.front(); 61 q.pop(); 62 book[u] = 0; 63 for(int i = h2[u]; i; i = e2[i].nxt) { 64 int v = e2[i].to; 65 if(dis[v] < dis[u] + node[v]) { 66 dis[v] = dis[u] + node[v]; 67 if(!book[v]) { 68 book[v] = 1; 69 q.push(v); 70 } 71 } 72 } 73 } 74 } 75 int main() { 76 scanf("%d%d", &n, &m); 77 for(int i = 1; i <= m; i++) { 78 x[i] = read(), y[i] = read(); 79 add(x[i], y[i]); 80 } 81 for(int i = 1; i <= n; i++) 82 if(!dfn[i]) tarjan(i); 83 for(int i = 1; i <= m; i++) { 84 int u = sd[x[i]], v = sd[y[i]]; 85 if(u != v) { 86 add2(u, v); 87 add2(v, u+tot); 88 add2(u+tot, v+tot); 89 } 90 } 91 for(int i=1;i<=tot;i++) node[i+tot]=node[i]; 92 spfa(sd[1]); 93 printf("%d", dis[sd[1]+tot]); 94 return 0; 95 }

和aq重學了個縮點QAQ