/*这道题是没有重边的,求加几条边构成双联通,求边联通分量,先求出桥然后缩点,成一个棵树 找叶子节点的个数*/ #include<stdio.h>//用容器写在3177这个题上会超内存,但是用临界表过了 #include<string.h>/*此代码为临界表代码*/ #define N 5100 struct node { int u,v,next; }bian[N*4]; int dfn[N],low[N],index,f[N*4],n,head[N],yong; int Min(int a,int b) { return a>b?b:a; } void addedge(int u,int v) {//建边 bian[yong].u=u; bian[yong].v=v; bian[yong].next=head[u]; head[u]=yong++; } void tarjan(int u,int pre) {// dfn[u]=low[u]=++index; int i; for(i=head[u];i!=-1;i=bian[i].next) { int v=bian[i].v; if(i==(pre^1))continue; if(!dfn[v]) { tarjan(v,i); low[u]=Min(low[u],low[v]);// if(low[v]>dfn[u])//标记桥 f[i]=f[i^1]=1;//标记双向的边 } else low[u]=Min(low[u],dfn[v]); } } int cnt,c[N]; void dfs(int u,int fa) {//缩点 int i; c[u]=cnt;//不能放到循环里面, for(i=head[u];i!=-1;i=bian[i].next) { int v=bian[i].v; if(!f[i]&&!c[v]&&i!=(fa^1))//桥不能走,不能回头路,没有被缩过 dfs(v,i); } return ; } int degree[N]; int slove() { int i; cnt=1; memset(c,0,sizeof(c)); for(i=1;i<=n;i++)//缩点 if(!c[i]) { dfs(i,-1); cnt++; } memset(degree,0,sizeof(degree)); for(i=0;i<yong;i++) { int u,v; u=bian[i].u; v=bian[i].v; if(c[u]!=c[v]) {//所有边中 degree[c[u]]++; degree[c[v]]++;//记录度数 } } int leave=0; for(i=1;i<cnt;i++) {//度数为一的叶子节点,因为为双向边 if(degree[i]==2) leave++; } return (leave+1)/2; } int main() { int m,i,a,b,ans; while(scanf("%d%d",&n,&m)!=EOF) { memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(f,0,sizeof(f)); yong=0; memset(head,-1,sizeof(head)); index=0; while(m--){ scanf("%d%d",&a,&b); addedge(a,b); addedge(b,a); } for(i=1;i<=n;i++) if(!dfn[i]) tarjan(i,-1); ans=slove(); printf("%d\n",ans); } return 0; }
poj 3177&&3352 求边双联通分量,先求桥,然后求分量( 临界表代码)
转载本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
【图论算法及模版】割点,割边,强联通分量,点双联通分量,边双联通分量
[原]【图
图论 割点 强连通分量 连通图 -
poj 3177-3352边双联通
买一送一啊 3177和3352的区别在于3177数据有重边!但是我先做3177的 那么就直接ctrl+c+v搞33
无向图 双联通 缩点 #include i++ -
POJ 3352 Road Construction(边双连通分量,桥,tarjan)
题解转自http://blog.csdn.net/lyy289065406/article/details/676237
连通分量 缩点 边双连通分量 #include 结点