tarjan 求点双边双
点双
1 #include<iostream> 2 #include<cstdio> 3 #include<bitset> 4 #include<queue> 5 #include<vector> 6 using namespace std; 7 const int N=100050,M=200020; 8 int fr1[M*2],fr2[M*2],dfn[N],low[N],stack[N*2],fa[N*2][23],ans[N],c[N*2],s[N*2],d[N*2],du[N],rt,top,num,tp,cnt,tt,n,m;//注意这里存点双的数组要开两倍 9 bool cut[N]; 10 vector<int>dcc[N]; 11 struct node{int fr,to,pr;}mo1[M*2],mo2[M*2]; 12 void add1(int x,int y) 13 { 14 mo1[++tt].fr=x;mo1[tt].to=y; 15 mo1[tt].pr=fr1[x];fr1[x]=tt; 16 } 17 void add2(int x,int y) 18 { 19 mo2[++tp].fr=x;mo2[tp].to=y; 20 mo2[tp].pr=fr2[x];fr2[x]=tp; 21 } 22 int rd() 23 { 24 char cc=getchar(); 25 int s=0,w=1; 26 while(cc<'0'||cc>'9') {if(cc=='-') w=-1;cc=getchar();} 27 while(cc>='0'&&cc<='9') s=(s<<3)+(s<<1)+cc-'0',cc=getchar(); 28 return s*w; 29 } 30 void tarjan(int x) 31 { 32 low[x]=dfn[x]=++num; 33 stack[++top]=x; 34 int son=0; 35 if(x==rt&&fr1[x]==0) 36 { 37 dcc[++cnt].push_back(x); 38 return; 39 } 40 for(int i=fr1[x];i;i=mo1[i].pr) 41 { 42 int y=mo1[i].to; 43 if(!dfn[y]) 44 { 45 tarjan(y); 46 low[x]=min(low[x],low[y]); 47 if(low[y]>=dfn[x]) 48 { 49 int z;son++;cnt++; 50 if(x!=rt||son>1) cut[x]=1; 51 do{ 52 z=stack[top--]; 53 dcc[cnt].push_back(z); 54 }while(y!=z);//理解:不能弹到x,因为x还要属于其他点双 55 dcc[cnt].push_back(x); 56 } 57 } 58 else low[x]=min(low[x],dfn[y]); 59 } 60 } 61 void predfs(int x) 62 { 63 for(int i=1;i<=20;i++) fa[x][i]=fa[fa[x][i-1]][i-1]; 64 for(int i=fr2[x];i;i=mo2[i].pr) 65 { 66 int to=mo2[i].to; 67 if(to==fa[x][0]) continue; 68 fa[to][0]=x; 69 d[to]=d[x]+1; 70 predfs(to); 71 } 72 } 73 int LCA(int x,int y) 74 { 75 if(d[x]<d[y]) swap(x,y); 76 for(int i=20;~i;i--) 77 if(d[fa[x][i]]>=d[y]) x=fa[x][i]; 78 if(x==y) return x; 79 for(int i=20;~i;i--) 80 if(fa[x][i]!=fa[y][i])//板子一定要打对 81 x=fa[x][i],y=fa[y][i]; 82 return fa[x][0]; 83 } 84 void dfs(int x) 85 { 86 for(int i=fr2[x];i;i=mo2[i].pr) 87 { 88 int to=mo2[i].to; 89 if(to==fa[x][0])continue; 90 dfs(to); 91 s[x]+=s[to]; 92 } 93 } 94 int main() 95 { 96 int q; 97 n=rd();m=rd();q=rd(); 98 for(int i=1,x,y;i<=m;i++) 99 { 100 x=rd(),y=rd(); 101 add1(x,y);add1(y,x); 102 } 103 for(int i=1;i<=n;i++) if(!dfn[i]) rt=i,tarjan(i); 104 num=cnt; 105 for(int i=1;i<=n;i++) if(cut[i]) c[i]=++num;//这就是为啥要开两倍,所有割点重新开 106 for(int i=1;i<=cnt;i++) 107 for(int j=0;j<dcc[i].size();j++) 108 { 109 int x=dcc[i][j]; 110 if(cut[x]) add2(i,c[x]),add2(c[x],i); 111 else c[x]=i; 112 } 113 d[1]=1;predfs(1); 114 for(int i=1,x,y,lca;i<=q;i++) 115 { 116 x=rd();y=rd(); 117 if(!cut[x])ans[x]++; 118 if(!cut[y])ans[y]++; 119 if(c[x]==c[y]) continue; 120 x=c[x];y=c[y];lca=LCA(x,y); 121 s[x]++,s[y]++,s[lca]--,s[fa[lca][0]]--; 122 } 123 dfs(1); 124 for(int i=1;i<=n;i++) 125 if(cut[i]) ans[i]=s[c[i]]; 126 for(int i=1;i<=n;i++) 127 printf("%d\n",ans[i]); 128 }
边双
#include<iostream> #include<cstdio> #include<bitset> #include<queue> #include<vector> using namespace std; const int N=10050,M=20020; int fr[M*2],ft[M*2],dfn[N],low[N],stack[N],c[N],du[N],rt,top,num,dcc,cnt,tt=1,n,m;//从1开始编 bool ins[N],ed[M]; struct node{int fr,to,pr;}mo[M*2],no[M*2]; void add(int x,int y) { mo[++tt].fr=x;mo[tt].to=y; mo[tt].pr=fr[x];fr[x]=tt; } int rd() { char cc=getchar(); int s=0,w=1; while(cc<'0'||cc>'9') {if(cc=='-') w=-1;cc-getchar();} while(cc>='0'&&cc<='9') s=(s<<3)+(s<<1)+cc-'0',cc=getchar(); return s*w; } void tarjan(int x,int id) { low[x]=dfn[x]=++num; for(int i=fr[x];i;i=mo[i].pr) { int y=mo[i].to; if(!dfn[y]) { tarjan(y,i); low[x]=min(low[x],low[y]); if(low[y]>dfn[x]) ed[i]=ed[i^1]=1;//0,1 |2,3 |4,5配对,因此一定要从1开始编号 } else if(i!=(id^1)) low[x]=min(low[x],dfn[y]); } } void dfs(int x) { c[x]=dcc; for(int i=fr[x];i;i=mo[i].pr) { int y=mo[i].to; if(c[y]||ed[i]) continue; dfs(y); } } int main() { n=rd();m=rd(); for(int i=1,x,y;i<=m;i++) { x=rd(),y=rd(); add(x,y);add(y,x); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,0); for(int i=1;i<=n;i++) if(!c[i]) ++dcc,dfs(i);//dfs重新搜边双 for(int i=2;i<=tt;i++) { int x=mo[i].fr,y=mo[i].to; if(c[x]==c[y]) continue; du[c[y]]++; } int ans=1; for(int i=1;i<=dcc;i++) if(du[i]==1) ans++; printf("%d\n",ans>>1); } /* g++ 1.cpp -o 1 ./1 7 7 1 2 2 3 3 4 2 5 4 5 5 6 5 7 */
Zeit und Raum trennen dich und mich.时空将你我分开。