标签:
题意:已知无向图,问添加最少的边使之成为边双连通图
思路:显然先缩点成一棵树,添加最少边使一棵树的边双连通
此处有结论:对于一棵树添加(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