众所周知,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 }
scc缩点

相关文章: