众所周知,Tarjan是毒瘤...先%为敬。%%%%%%%%%%%%
有这么一些毒瘤:
有向图求强连通分量并缩点。
无向图求点割点并缩点。
无向图求割边并缩点。
1.有向图求强连通分量并缩点。
这.....我又调了两天才搞出板子来。
洛谷P3387
1 #include <cstdio> 2 #include <algorithm> 3 #include <queue> 4 const int N = 10010, M = 100010; 5 6 struct Edge { 7 int u, v, nex; 8 }edge[M]; int top; 9 int e[N], dfn[N], low[N], num; 10 int stk[N], t, val[N]; 11 bool in_stk[N]; 12 13 Edge scc_edge[M]; 14 int scc_e[N], scc_top, scc_in[N], scc_cnt, scc_val[N]; 15 int topo[N], fr[N]; 16 17 inline void add(int x, int y) { 18 ++top; 19 edge[top].u = x; 20 edge[top].v = y; 21 edge[top].nex = e[x]; 22 e[x] = top; 23 return; 24 } 25 26 inline void scc_add(int x, int y) { 27 scc_top++; 28 scc_edge[scc_top].v = y; 29 scc_edge[scc_top].nex = scc_e[x]; 30 scc_e[x] = scc_top; 31 scc_in[y]++; 32 return; 33 } 34 35 void tarjan(int x) { 36 dfn[x] = low[x] = ++num; 37 stk[++t] = x; 38 in_stk[x] = 1; 39 for(int i = e[x]; i; i = edge[i].nex) { 40 int y = edge[i].v; 41 if(!dfn[y]) { 42 tarjan(y); 43 low[x] = std::min(low[x], low[y]); 44 } 45 else if(in_stk[y]) { 46 low[x] = std::min(low[x], dfn[y]); 47 } 48 } 49 if(dfn[x] == low[x]) { 50 scc_cnt++; 51 int y; 52 do { 53 y = stk[t--]; 54 in_stk[y] = 0; 55 fr[y] = scc_cnt; 56 scc_val[scc_cnt] += val[y]; 57 }while(y != x); 58 } 59 return; 60 } 61 62 inline void topo_sort() { 63 std::queue<int> Q; 64 int temp = 0; 65 for(int i = 1; i <= scc_cnt; i++) { 66 if(!scc_in[i]) { 67 Q.push(i); /// error : topo[++num] = i; 68 } 69 } 70 while(!Q.empty()) { 71 int x = Q.front(); 72 Q.pop(); 73 topo[++temp] = x; 74 for(int i = scc_e[x]; i; i = scc_edge[i].nex) { 75 int y = scc_edge[i].v; 76 scc_in[y]--; 77 if(!scc_in[y]) { 78 Q.push(y); 79 } 80 } 81 } 82 return; 83 } 84 85 int main() { 86 int n, m; 87 scanf("%d%d", &n, &m); 88 for(int i = 1; i <= n; i++) { 89 scanf("%d", &val[i]); 90 } 91 for(int i = 1, x, y; i <= m; i++) { 92 scanf("%d%d", &x, &y); 93 if(x == y) { 94 continue; /// error : space 95 } 96 add(x, y); 97 } 98 for(int i = 1; i <= n; i++) { 99 if(!dfn[i]) { 100 tarjan(i); 101 } 102 } 103 104 for(int i = 1; i <= top; i++) { 105 int x = edge[i].u; 106 int y = edge[i].v; 107 if(fr[x] != fr[y]) { 108 scc_add(fr[x], fr[y]); 109 } 110 } 111 int ans = 0; 112 topo_sort(); 113 for(int i = scc_cnt; i; i--) { 114 int x = topo[i]; 115 int temp = 0; 116 for(int j = scc_e[x]; j; j = scc_edge[j].nex) { 117 int y = scc_edge[j].v; 118 temp = std::max(temp, scc_val[y]); 119 } 120 scc_val[x] += temp; 121 ans = std::max(ans, scc_val[x]); 122 } 123 printf("%d\n", ans); 124 return 0; 125 }