标签:
题意:已知无向图,问添加最少的边使之成为边双连通图
思路:显然先缩点成一棵树,添加最少边使一棵树的边双连通
此处有结论:对于一棵树添加(1+leaf)>>1 条无向边就能构造成一个双连通图,构造方法显然(脑补一下
//216K 63MS C++ 1754B #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int N = 1010; struct node { int v,next; }es[N*N]; int head[N]; int n,m; int low[N],dfn[N],index; int indeg[N]; void ini() { memset(head,-1,sizeof(head)); memset(dfn,0,sizeof(dfn)); index=0; memset(indeg,0,sizeof(indeg)); } void tarjan(int u,int pa) { dfn[u]=low[u]=++index; for(int i=head[u];~i;i=es[i].next) { int v=es[i].v; if(dfn[v]==0) { tarjan(v,u); low[u]=min(low[u],low[v]); } if(v!=pa) low[u]=min(low[u],low[v]); } } int main() { while(~scanf("%d%d",&n,&m)) { ini(); for(int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); es[i].v=v; es[i].next=head[u]; head[u]=i; es[i+m].v=u; es[i+m].next=head[v]; head[v]=i+m; } for(int i=1;i<=n;i++) if(dfn[i]==0) tarjan(i,-1); for(int u=1;u<=n;u++) { for(int i=head[u];~i;i=es[i].next) { int v= es[i].v; if(low[v]==low[u]) continue; indeg[low[u]]++; } } int leaf=0; for(int i=1;i<=n;i++) if(indeg[i]==1) leaf++; printf("%d\n",(leaf+1)/2); } return 0; }
POJ 3352 Road Construction(添最少边构造边双连通图的结论)
标签:
原文地址:http://blog.csdn.net/kalilili/article/details/45228351