【模板】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 }
> 别忘了 总有人在等着你

浙公网安备 33010602011771号