【模板】Tarjan

强连通分量

Code:

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define clr(t) memset(t,0,sizeof(t))
  6 #define rep(i,a,n) for(int i = a;i <= n;i++)
  7 #define per(i,n,a) for(int i = n;i >= a;i--)
  8 #define inf 2147483647
  9 #define eps 1e-7
 10 using namespace std;
 11 typedef long long ll;
 12 int read() {
 13     int as = 0,fu = 1;
 14     char c = getchar();
 15     while(c < '0' || c > '9') {
 16         if(c == '-') fu = -1;
 17         c = getchar();
 18     }
 19     while(c >= '0' && c <= '9') {
 20         as = as * 10 + c  - '0';
 21         c = getchar();
 22     }
 23     return as * fu;
 24 }
 25 const int N = 200005;
 26 //head
 27 int n,m,ans;
 28 int v[N],sum[N];
 29 int head[N],nxt[N],mo[N],cnt;
 30 void add(int x,int y) {
 31     mo[++cnt] = y;
 32     nxt[cnt] = head[x];
 33     head[x] = cnt;
 34     return ;
 35 }
 36 
 37 int dfn[N],low[N],crt;
 38 int stk[N],top;
 39 int bel[N],cur;
 40 bool ins[N];
 41 void tarjan(int x) {
 42     dfn[x] = low[x] = ++crt;
 43     stk[++top] = x,ins[x] = 1;
 44     for(int i = head[x];i;i = nxt[i]) {
 45         int sn = mo[i];
 46         if(dfn[sn] == 0) {
 47             tarjan(sn);
 48             low[x] = min(low[x],low[sn]);
 49         } else if(ins[sn]) {
 50             low[x] = min(low[x],dfn[sn]);
 51         }
 52     }
 53     if(low[x] == dfn[x]) {
 54         int t = stk[top--];
 55         ins[t] = 0;
 56         bel[t] = ++cur;
 57         sum[cur] = v[t];
 58         while(t != x) {
 59             t = stk[top--],ins[t] = 0;
 60             bel[t] = cur;
 61             sum[cur] += v[t];
 62             //每个块的新值 
 63         }
 64     }
 65     return;
 66 }
 67 
 68 int str[N],stp[N];
 69 int dp[N];
 70 void DAG(int x) {
 71     if(dp[x]) return;
 72     dp[x] = sum[x];
 73     //选择最大的一个往下走 
 74     int maxx = 0;
 75     for(int i = head[x] ;i;i = nxt[i]) {
 76         int sn = mo[i];
 77         if(dp[sn] == 0) DAG(sn);
 78         maxx = max(maxx,dp[sn]);
 79     }
 80     dp[x] += maxx;
 81     return;
 82 }
 83 
 84 
 85 int main() {
 86     n = read();
 87     m = read();
 88     rep(i,1,n) v[i] = read();        
 89     rep(i,1,m) {
 90         str[i] = read();
 91         stp[i] = read();
 92         add(str[i],stp[i]);
 93     }
 94     rep(i,1,n) if(!dfn[i]) tarjan(i);
 95     
 96     cnt = 0;
 97     clr(head);
 98     clr(nxt);
 99     clr(mo);
100     rep(i,1,m) 
101         if(bel[str[i]] != bel[stp[i]])
102             add(bel[str[i]],bel[stp[i]]);
103     rep(i,1,cur) {
104         //选择一个没有入度的点 
105         if(dp[i] == 0) {
106             DAG(i);
107             ans = max(ans,dp[i]);
108         }
109     }
110     printf("%d\n",ans); 
111     return 0;
112 }

点双

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #define rep(i,a,n) for(int i = a;i <= n;i++)
 6 #define per(i,n,a) for(int i = n;i >= a;i--)
 7 #define inf 2147483647
 8 using namespace std;
 9 typedef long long ll;
10 int read() {
11     int as = 0,fu = 1;
12     char c = getchar();
13     while(c < '0' || c > '9') {
14         c == '-' ? fu = -1 : 0;
15         c = getchar();
16     }
17     while(c >= '0' && c <= '9') {
18         as = as * 10 + c - '0';
19         c = getchar();
20     }
21     return as * fu;
22 }
23 #define N 100005
24 //head
25 int n,m;
26 int head[N],mo[N<<1],nxt[N<<1],cnt;
27 int dfn[N],low[N],tot,idx;
28 bool iscut[N];
29 
30 inline void add(int x,int y) {
31     mo[++cnt] = y;
32     nxt[cnt] = head[x];
33     head[x] = cnt;
34     return;
35 }
36 
37 void Tarjan(int x,int rt) {
38     dfn[x] = low[x] = ++idx;
39     int cld = 0;
40     for(int i = head[x]; i; i = nxt[i]) {
41         int sn = mo[i];
42         if(!dfn[sn]) {
43             Tarjan(sn,rt);
44             low[x] = min(low[x],low[sn]);
45             if(low[sn] >= dfn[x] && x != rt) iscut[x] = true;
46             if(x == rt) cld++;
47         }
48         low[x] = min(low[x],dfn[sn]);
49     }
50     if(cld >= 2 && x == rt) iscut[x] = true;
51     return;
52 }
53 
54 int main() {
55     n = read();
56     m = read();
57     rep(i,1,m) {
58         int x = read();
59         int y = read();
60         add(x,y);
61         add(y,x);
62     }
63     rep(i,1,n) if(!dfn[i]) Tarjan(i,i);
64     rep(i,1,n) if(iscut[i]) tot++;
65     printf("%d\n",tot);
66     rep(i,1,n) if(iscut[i]) printf("%d ",i);
67     puts("");
68     return 0;
69 }

 

posted @ 2018-10-03 22:50  白怀潇  阅读(119)  评论(0)    收藏  举报