您的位置:首页 > 其它

poj3177 Redundant Paths 双连通分量

2015-08-29 18:52 337 查看
题意:给你一个无向图,问最少增加几条边能让这个无向图变成双连通的,与强连通不同,双连通要求任意两个点之间都有两条不同的路相连,即图中不存在割边。

解法:利用Trajan算法,找出图中的双连通分量,缩点后图变成了一棵树,统计树中度为1的节点,然后在没两个度为1的节点之间连一条边即可。

看了一下午Trajan算法也没有能理解整个算法, 暂时先当个模板存起来吧

AC代码:

<span style="font-family:KaiTi_GB2312;font-size:18px;">#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#define maxn 10005
using namespace std;
struct EDGE{
int v;
int next;
}edge[maxn*2];
int h,f,r,dfn[maxn],low[maxn],cnt,edgehead[maxn],scc,belong[maxn],degree[maxn]; //统计各个节点的度
int stack[maxn], instack[maxn], top;
void addedge(int u, int v)
{
edge[h].v = v;
edge[h].next = edgehead[u];
edgehead[u] = h++;
}
void Trajan(int u, int fa) //Trajan算法计算双连通分量
{
low[u] = dfn[u] = ++cnt;
stack[++top] = u;
instack[u] = 1;
for(int i = edgehead[u]; i != -1; i = edge[i].next)
{
int v = edge[i].v;
if(i == (fa ^ 1))
continue;
if(!dfn[v])
{
Trajan(v, i);
low[u] = min(low[u], low[v]);
}
else if(instack[v])
low[u] = min(low[u], dfn[v]);
}
if(low[u] == dfn[u])
{
scc++;
while(1)
{
int v = stack[top--];
instack[v] = 0;
belong[v] = scc;
if(v == u)
break;
}
}
}
int main(){
scanf("%d%d",&f, &r);
memset(edgehead, -1, sizeof(edgehead));
memset(instack, 0, sizeof(instack));
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
scc = top = cnt = h = 0;
int a,b;
for(int i = 0; i < r; i++)
{
scanf("%d%d", &a, &b);
addedge(a,b);
addedge(b,a);
}
/*for(int i = 1; i <= f; i++)
{
for(int j = edgehead[i]; j != -1; j = edge[j].next)
printf("%d ",edge[j].v);
printf("\n");
}
Trajan(1, -1);*/
for(int i = 1; i <= f; i++)
{
if(!dfn[i])
Trajan(1, -1);
}
for(int i = 1; i <= f; i++)
{
for(int j = edgehead[i]; j != -1; j = edge[j].next)
{
int v = edge[j].v;
if(belong[i] != belong[v])
degree[belong[i]]++;
}
}
int ans = 0;
for(int i = 1; i <= f; i++)
if(degree[i] == 1)
ans++;
ans = (ans + 1)/2;
printf("%d\n",ans);
}
</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm