pku 3117 pku 3352 割边以及双连通分量问题

http://poj.org/problem?id=3177

http://poj.org/problem?id=3352

把3177的代码直接贴到3352也就a了。

3177:

题意是给一个图,注意这里有重边,问至少添加多少条边才能使是该图成为边双连通图。首先求出该图中的割边(桥)然后删除桥,剩下的就都是边双连通分量了,然后将其缩成一个点,再把桥加上就死形成了一棵树,边连通度为1.记录叶子节点数ans,则至少添加(ans+1)/2个节点才能使原图成为边双连通图。

此时low[]值相同的是同一个连通分量,注意在求tarjan是不能染low[i]取到low[ifather]的值,这样整个图的low[i]就都是1了;;

View Code
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#define maxn 5010
using namespace std;
int low[maxn],dfn[maxn],deg[maxn];
bool instack[maxn];
int bcnt,index;
int n,m;
vector<int>g[maxn];
bool isok(int u,int v)
{
for (int i = 0; i < g[u].size(); ++i)
{
if (v == g[u][i])
return false;
}
return true;
}
void init()
{
for (int i = 0;i < maxn; ++i)
{
g[i].clear();
low[i] = dfn[i] = deg[i] = 0;
instack[i] = false;
}
index = bcnt = 0;
}
void tarjan(int i,int ifa)
{
int j,k;
low[i] = dfn[i] = ++index;
for (k = 0; k < g[i].size(); ++k)
{
j = g[i][k];
if (j == ifa)//注意这里的处理
{
continue;
}
if (!dfn[j]) tarjan(j,i);
low[i] = min(low[i],low[j]);
}
}
int main()
{
//freopen("d.txt","r",stdin);
int i,j,k,x,y;
while (~scanf("%d%d",&n,&m))
{
init();
for (i = 0; i < m; ++i)
{
cin>>x>>y;
if (isok(x,y))
{
g[x].push_back(y);
g[y].push_back(x);
}
}
for (i = 1; i <= n; ++i)
{
if (!dfn[i]) tarjan(i,-1);
}
for (i = 1; i <= n; ++i)
{
for (j = 0; j < g[i].size(); ++j)
{
k = g[i][j];
if (low[i] != low[k])
deg[low[i]]++;
}
}
int ans = 0;
for (i = 1; i <= index; ++i)
{
//printf(">>%d\n",deg[i]);
if (deg[i] == 1) ans++;
}
printf("%d\n",(ans + 1)/2);
}
return 0;
}



posted @ 2012-02-15 15:17  E_star  阅读(326)  评论(0编辑  收藏  举报