您的位置:首页 > 其它

双连通分支 POJ 3177 3352

2010-10-28 21:34 288 查看
http://poj.org/problem?id=3177

/*
题目大意:给定一个双向连通的公路网,当某些公路路段检修的时候可能会由于该段公路不通,
可能会使某些旅游点之间无法通行,求至少新建多少条公路,使得任意对一段公路进行检修的时候,
所有的旅游景点之间仍然畅通;
---双连通分量分两种,一种是删除一条边仍然连通的,叫做边连通分量,以桥为分割,
另外一个是删除一个点仍然连通,叫点连通分量.
---其实把所有的桥都找出来就可以进行划分了,由于在计算连通分量的tarjan算法中,如果两个点是在同一个边
连通分量中,那么他们的low值是一样的,所以就可以直接通过tarjan算法求出所有的low值,
然后判断low值是否相同就可以判断是否 在同一个边连通分量中。
---点双连通分量:在计算点连通分量的算法中,是以割点为分界的,和边连通分量的求法差不多,
不过需要多增加一个栈来记录经过的点,并且要注意和强连通分量所用的栈的不同,在点连通分量中,
割点是可以在多个点连通分量中的,所以这里的退栈是有一些地方要注意的,
*/
#include <iostream>
#include <vector>
using namespace std;

const int MAXN = 5001;
vector< vector<int> > adj;
bool hash[MAXN][MAXN];
int cnt,low[MAXN],pre[MAXN],visit[MAXN],degree[MAXN];

void dfs(int u,int v)
{
visit[u]=1;
pre[u]=cnt++, low[u]=pre[u];
int i, len=adj[u].size();
for(i=0;i<len;i++)
{
if(adj[u][i]==v) continue;
if(!visit[adj[u][i]])
dfs(adj[u][i],u);
if(low[adj[u][i]]<low[u])
low[u]=low[adj[u][i]];
}
visit[u]=2;
}
int main()
{
//	freopen("in.txt", "r", stdin);
int i,j,u,v,n,m,len,ans;
while(scanf("%d %d",&n,&m)!=EOF)
{
adj.assign(n+1,vector<int>());
memset(hash,false,sizeof(hash));
while(m--)
{
scanf("%d %d", &u, &v);
if(!hash[u][v])
{
hash[u][v]=true;
adj[u].push_back(v),adj[v].push_back(u);
}
}
memset(visit,0,sizeof(visit));
cnt=0,dfs(1,1);
memset(degree,0,sizeof(degree));
for(i=1;i<=n;i++)
{
len=adj[i].size();
for(j=0;j<len;j++)
if(low[i]!=low[adj[i][j]])
degree[low[i]]++;
}
for(ans=i=0;i<=n;i++)
if(degree[i]==1)
ans++;
printf("%d/n",(ans+1)/2);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: