这里是tarjan的基础知识,
求割点和割边
先来求割边,
1 #include <cstdio> 2 #include <iostream> 3 #include <bits/stdc++.h> 4 using namespace std; 5 typedef long long ll; 6 typedef unsigned long long ull; 7 8 #define ls (t<<1) 9 #define rs ((t<<1)|1) 10 #define mid ((l+r)>>1) 11 12 #define mk make_pair 13 #define pb push_back 14 #define fi first 15 #define se second 16 17 #define MAXN 100001 18 struct edge { 19 int v,nxt; 20 } e[MAXN*2]; 21 int head[MAXN]; 22 bool qiao[MAXN*2]; 23 int dfn[MAXN],low[MAXN]; 24 int n,m,cnt,num; 25 int c[MAXN],dcc; 26 //c[i]为i节点所在边双联通块编号 27 void add(int x,int y) { 28 e[++cnt].v=y,e[cnt].nxt=head[x],head[x]=cnt; 29 } 30 void tarjan(int x,int fa) { 31 dfn[x]=low[x]=++num; 32 for (int i=head[x]; i; i=e[i].nxt) { 33 int y=e[i].v; 34 if (!dfn[y]) { 35 tarjan(y,i); 36 low[x]=min(low[x],low[y]); 37 if (low[y]>dfn[x]) { 38 qiao[i]=qiao[i^1]=1; 39 } 40 } else if(i!=(fa^1)) { 41 low[x]=min(low[x],dfn[y]); 42 } 43 } 44 } 45 46 void dfs(int x) { 47 c[x]=dcc; 48 for (int i=head[x];i;i=e[i].nxt) { 49 int y=e[i].v; 50 if (c[y]||qiao[i]) continue; 51 dfs(y); 52 } 53 } 54 55 struct newedge{ 56 int v,nxt; 57 }newe[MAXN*2]; 58 int newhead[MAXN],newcnt; 59 void newadd(int x,int y) { 60 newe[++newcnt].v=y; 61 newe[newcnt].nxt=newhead[x]; 62 newhead[x]=newcnt; 63 } 64 65 int main() { 66 cin>>n>>m; 67 cnt=1; 68 for (int i=1,x,y; i<=m; i++) { 69 cin>>x>>y; 70 add(x,y),add(y,x); 71 } 72 for (int i=1; i<=n; i++) { 73 if (!dfn[i]) { 74 tarjan(i,0); 75 } 76 } 77 for (int i=1;i<=n;i++) { 78 if (!c[i]) { 79 ++dcc; 80 dfs(i); 81 } 82 } 83 for (int i=2; i<cnt; i+=2) { 84 if (qiao[i]) { 85 cout<<e[i^1].v<<" "<<e[i].v<<"是桥"<<endl; 86 } 87 } 88 cout<<endl; 89 cout<<"边双联通块有"<<dcc<<"块"<<endl; 90 for (int i=1;i<=n;i++) { 91 cout<<i<<" "<<"belongs"<<" "<<c[i]<<endl; 92 } 93 newcnt=1; 94 for (int i=2;i<=cnt;i++) { 95 int x=e[i^1].v,y=e[i].v; 96 if (c[x]==c[y]) continue; 97 newadd(c[x],c[y]); 98 } 99 cout<<"缩点后点数"<<dcc<<" 边数"<<newcnt/2<<endl; 100 for (int i=2;i<newcnt;i++) { 101 cout<<newe[i^1].v<<" "<<newe[i].v<<"是一条边"<<endl; 102 } 103 return 0; 104 } 105 106 /* 107 12 15 108 1 2 109 1 3 110 2 3 111 2 4 112 3 5 113 4 5 114 1 6 115 6 7 116 6 8 117 7 8 118 7 9 119 7 10 120 10 11 121 10 12 122 11 12 123 */
下面是割点
#include <cstdio> #include <iostream> #include <bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; #define pb push_back #define MAXN 100001 struct edge { int v,nxt; } e[MAXN*2]; int head[MAXN]; bool cut[MAXN]; int dfn[MAXN],low[MAXN]; int n,m,cnt,num,root; vector <int> dcc[MAXN]; int ccnt;//用于存dcc数组 //dcc[i]保存编号为i的点双联通块内全部节点 int s[MAXN],top;//站 int c[MAXN]; //c[i]表示表示i所属v-DCC编号 void add(int x,int y) { e[++cnt].v=y,e[cnt].nxt=head[x],head[x]=cnt; } void tarjan(int x) { dfn[x]=low[x]=++num; s[++top]=x; if (x!=root&&head[x]==0) { dcc[++ccnt].pb(x); return; } int flag=0; for (int i=head[x]; i; i=e[i].nxt) { int y=e[i].v; if (!dfn[y]) { tarjan(y); low[x]=min(low[x],low[y]); if (low[y]>=dfn[x]) { flag++; if (x!=root||flag>1) { cut[x]=1; } ccnt++; int z; do{ z=s[top--]; dcc[ccnt].pb(z); }while(z!=y); dcc[ccnt].pb(x); } } else low[x]=min(low[x],dfn[y]); } } struct newedge{ int v,nxt; }newe[MAXN*2]; int newhead[MAXN],tc; int new_id[MAXN]; void newadd(int x,int y) { newe[++tc].v=y; newe[tc].nxt=newhead[x]; newhead[x]=tc; } int main() { cin>>n>>m; cnt=1; for (int i=1,x,y; i<=m; i++) { cin>>x>>y; if (x==y) continue; add(x,y),add(y,x); } for (int i=1; i<=n; i++) { if (!dfn[i]) { root=i; tarjan(i); } } for (int i=1; i<=n; i++) { if (cut[i]) { cout<<i<<" "; } } cout<<"是个割点"<<endl; for (int i=1;i<=ccnt;i++) { cout<<"v-DCC "<<i<<" : "; for (int j=0;j<dcc[i].size();j++) { cout<<" "<<dcc[i][j]; } cout<<endl; } num=ccnt; for (int i=1;i<=n;i++) { if (cut[i]) new_id[i]=++num; } tc=1; for (int i=1;i<=ccnt;i++) { for (int j=0;j<dcc[i].size();j++) { int x=dcc[i][j]; if (cut[x]) { newadd(i,new_id[x]); newadd(new_id[x],i); } else c[x]=i; } } cout<<"缩点后森林点数 "<<num<<" 边数 "<<tc/2<<endl; printf("编号 1~%d 的为原图v-DCC,编号 >%d 的为原图割点 ",ccnt,ccnt); for (int i=2;i<tc;i+=2) { cout<<newe[i^1].v<<" "<<newe[i].v<<endl; } return 0; } /* 12 15 1 2 1 3 2 3 2 4 3 5 4 5 1 6 6 7 6 8 7 8 7 9 7 10 10 11 10 12 11 12 */ /* 8 11 1 2 1 5 2 5 2 3 3 4 4 5 1 6 6 7 6 8 6 9 8 9 */