您的位置:首页 > 其它

Poj 3177 Redundant Paths (双连通分支+节点统计)

2015-07-22 20:45 399 查看
题目描述:

  给出一个无向的连通图,问最少加入几条边,才能使所给的图变为无桥的双连通图?

解题思路:

  可以求出原图中所有的不包含桥的所有最大连通子图,然后对连通子图进行标记缩点,统计度为1的叶子节点leaf有多少个,答案就是(leaf+1)/2;

  这个题目有重边,在处理的时候要注意下。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int maxn = 5005;
struct node
{
int to, next;
} edge[maxn*2];

int low[maxn], dfn[maxn], head[maxn], id[maxn], in[maxn];
int stack[maxn], tot, ntime, cnt, top, In;
void init ()
{
tot = ntime = cnt = top = In = 0;
memset (in, 0, sizeof(in));
memset (id, 0, sizeof(id));
memset (low, 0, sizeof(low));
memset (dfn, 0, sizeof(dfn));
memset (head, -1, sizeof(head));
memset (stack, 0, sizeof(stack));
}
void Add (int from, int to)
{
edge[tot].to = to;
edge[tot].next = head[from];
head[from] = tot++;
}
void Tarjan (int u, int father)
{
int k = 0;
low[u] = dfn[u] = ++ntime;
stack[top++] = u;
for (int i=head[u]; i!=-1; i=edge[i].next)
{
int v = edge[i].to;
if (v==father && !k)
{//判定重边
k++;
continue;
}
if (!dfn[v])
{
Tarjan (v, u);
low[u] = min (low[v], low[u]);
}
else
low[u] = min (low[u], dfn[v]);
}
if (low[u] == dfn[u])
{
cnt ++;
while (1)
{//对同一个连通块内的点染色
int v = stack[--top];
id[v] = cnt;
if (v == u)
break;
}
}
}
int main ()
{
int n, m;
while (scanf ("%d %d", &n, &m) != EOF)
{
init ();
while (m --)
{
int u, v;
scanf ("%d %d", &u, &v);
Add (u, v);
Add (v, u);
}
for (int i=1; i<=n; i++)
if (!dfn[i])
Tarjan (i, 0);
for (int i=1; i<=n; i++)
for (int j=head[i]; j!=-1; j=edge[j].next)
{
int u = id[i];
int v = id[edge[j].to];
if (v != u)
{//统计缩点后的图中每个点的度
in[v] ++;
in[u] ++;
}
}
for (int i=1; i<=cnt; i++)
if (in[i] == 2)//因为是无向图建图方式的原因,当度为2的时候才是叶子节点
In ++;
printf ("%d\n", (In+1)/2);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: