标签:hid har void lap push struct dfs else tor
模板向。
以前学的scc已经差不多可以倒着打了。求scc和缩点还是比较好搞的(当然,必经点和边确实没学)。
现在学一学求eDcc和vDcc的tarjan。
求eDcc,只要学会求桥,然后dfs染色即可,至于缩点就是枚举每条边然后新建图。
桥的判定要low[y]>dfn[x],因为只有这样才不能回到dfs树在x以上的位置。而且由于一些重边问题,tarjan开第二参量,确定low值不被自己更新,需要用到邻接表成对变换。
#include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<cstdio> #include<vector> #include<queue> #include<stack> #include<set> #include<map> using namespace std; int read(){ int sum=0,f=1;char x=getchar(); while(x<‘0‘||x>‘9‘){ if(x==‘-‘) f=-1; x=getchar(); }while(x>=‘0‘&&x<=‘9‘){ sum=sum*10+x-‘0‘; x=getchar(); }return sum*f; } struct EDGE{ int ed,nex; }edge[100],edgec[100]; int first[50],firstc[50],num=1,numc; int n,m; int dfn[50],low[50],bl[50]; int ord,ecc; bool bridge[100]; void add(int st,int ed){ edge[++num].ed=ed; edge[num].nex=first[st]; first[st]=first[st]; } void addc(int st,int ed){ edgec[++numc].ed=ed; edgec[numc].nex=firstc[st]; firstc[st]=numc; } void tarjan(int x,int in_edge){ dfn[x]=low[x]=++ord; for(int i=first[x];i;i=edge[i].nex){ int y=edge[i].ed; if(!dfn[y]){ tarjan(y); low[x]=min(low[x],low[y]); if(low[y]>dfn[x]) bridge[i]=bridge[i^1]=1; }else if(i!=(in_edge^1)) low[x]=min(low[x],dfn[y]); } } void dfs(int x){ bl[x]=ecc; for(int i=first[x];i;i=edge[i].nex){ int y=edge[i].ed; if(bl[y]||bridge[i]) continue; dfs(y); } } int main(){ n=read();m=read(); for(int i=1,x,y;i<=m;i++){ x=read();y=read(); 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(!bl[i]){ ecc++; dfs(i); } for(int i=2;i<=num;i++){ int x=edge[i].ed,y=edge[i^1].ed; if(bl[x]==bl[y]) continue; addc(bl[x],bl[y]); } }
求vDcc,要学会求割点,在求割点的程序里套上一个用vector存vDcc的子块即可。
割点的判定要low[y]>=dfn[x],而且因为搜索树的性质,需要单独判断根的情况。
缩点的时候因为一个割点可以在两个vDcc里,所以先将割点单独编号,然后建新边。
#include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<cstdio> #include<vector> #include<queue> #include<stack> #include<set> #include<map> using namespace std; struct EDGE{ int ed,nex; }edge[200],edgec[200]; int first[100],firstc[100]; int n,m,ord,top,root,vccnum,nvcn; int dfn[100],low[100],sta[101000],new_id[100],bl[100]; vector<int>vcc[100]; bool cut[100]; int read(){ int sum=0,f=1;char x=getchar(); while(x<‘0‘||x>‘9‘){ if(x==‘-‘) f=-1; x=getchar(); }while(x>=‘0‘&&x<=‘9‘){ sum=sum*10+x-‘0‘; x=getchar(); }return sum*f; } void add(int st,int ed){ edge[++num].ed=ed; edge[num].nex=first[st]; first[st]=num; } void addc(int st,int ed){ edgec[++numc].ed=ed; edgec[numc].nex=firstc[st]; firstc[st]=numc; } void tarjan(int x){ dfn[x]=low[x]=++ord; sta[++top]=x; if(root==x&&first[x]==0){ vcc[++vccnum].push_back(x); return ; } int child=0; for(int i=first[x];i;i=edge[i].nex){ int y=edge[i].ed; if(!dfn){ tarjan(y); low[x]=min(low[x],low[y]); if(low[y]>=dfn[x]){ child++; if((x==root&&child>=2)||(x!=root&&child>0)) cut[x]=1; vcc[++vccnum].push_back(x); int p; do{ p=sta[top--]; vcc[vccnum].push_back(p); }while(p!=y); } }else low[x]=min(low[x],dfn[y]); } } int main(){ n=read();m=read(); for(int i=1,x,y;i<=m;i++){ x=read();y=read(); add(x,y);add(y,x); } for(int i=1;i<=n;i++) if(!dfn[i]) root,tarjan(i); nvcn=vccnum; for(int i=1;i<=n;i++) if(cut[i]) new_id[i]=++nvcn; for(int i=1;i<=vccnum;i++) for(int j=0;j<vcc[i].size();j++){ int x=vcc[i][j]; if(cut[x]){ addc(new_id[x],i); addc(i,new_id[x]); }else bl[x]=i; } }
以上代码均未测试,如有错误自行改正。
标签:hid har void lap push struct dfs else tor
原文地址:https://www.cnblogs.com/Yu-shi/p/11183312.html