您的位置:首页 > 其它

poj3352 利用边的双连通性质求解

2013-05-21 17:24 246 查看
给你一个无向图,求解至少需要添加几条边,就能保证删除任一条边时,图仍然是连通的

思路:

求解至少添加多少条边,可以使该图成为边的双连通图

利用tarjan算法:求解low[]值记录父亲结点,然后low[]相同的点,在一个连通分量中,然后缩点

求解出度为1的点的个数ans,答案就是(ans+1)/2;

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<string.h>
using namespace std;
const int Max=1111;
int low[Max];
int dfn[Max];
int cnt;
int Branch;
int dre[Max];
vector<int>Gra[Max];
int MIN(int a,int b)
{
return a>b?b:a;
}
void tarjan(int x,int fa)
{
low[x]=dfn[x]=cnt++;
for(int i=0;i<Gra[x].size();i++)
{
int u=Gra[x][i];
if(u==fa) continue;
if(!dfn[u])
{
tarjan(u,x);
low[x]=MIN(low[x],low[u]);
}
else if(low[x]>dfn[u])
low[x]=dfn[u];
}
}
void start(int n )
{
memset(dfn,0,sizeof(dfn));
cnt=1;
Branch=0;
for(int i=1;i<=n;i++)
{
if(!dfn[i])
{
tarjan(i,i);
Branch++;
}
}
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(dre,0,sizeof(dre));
for(int i=1;i<Max;i++)
Gra[i].clear();
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
Gra[u].push_back(v);
Gra[v].push_back(u);
}
start(n);
for(int i=1;i<=n;i++)
{
for(int j=0;j<Gra[i].size();j++)
{
if(low[i]!=low[Gra[i][j]])//记录出度:
dre[low[i]]++;
}
}
int  ans=0;
for(int i=1;i<cnt;i++)
if(dre[i]==1)
ans++;
printf("%d\n",(ans+1)/2);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: