题目链接:http://poj.org/problem?id=3177
题意:有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走。现已有m条路,求至少要新建多少条路,使得任何两个牧场之间至少有两条独立的路。两条独立的路是指:没有公共边的路,但
可以经过同一个中间顶点。
要先将图 强联通分量缩点, 在无向图中我们称为边双连通分量。
将所有边双连通分量求出来缩成点,就形成了一棵树,我们只要判断树的叶子结点的个数就行了。假设叶子节点的个数是 n 那么 就有 (n+1)/2 条边就能将这个图变成没有桥的 双连通图,判断一个点是否是叶子节点
只要判断这个点的度就行了,度为 1 的点就是叶子节点。
因此我们只需将叶子节点连在一起就可以了,需要建立(叶子节点的个数+1)/ 2;
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <stack>
#include <cstring>
using namespace std;
#define INF 0xfffffff
#define N 5100
int low[N], dfn[N], f[N], block[N],du[N], Is[N];
vector<vector<int> > G;
int n, Time, m, cnt;
stack<int>sta;
void Init()
{
G.clear();
G.resize(n+);
Time = cnt = ;
memset(low, , sizeof(low));
memset(dfn, , sizeof(dfn));
memset(du, , sizeof(du));
memset(f, , sizeof(f));
memset(Is, , sizeof(Is));
} void Tarjan(int u, int father)
{
f[u] = father;
dfn[u] = low[u] = ++Time;
int len = G[u].size(), v, k=;
sta.push(u);
Is[u] = ;
for(int i=; i<len; i++)
{
v = G[u][i];
if(v == father && !k)
{
k++;
continue;
}
if(!dfn[v])
{
Tarjan(v, u);
low[u] = min(low[u], low[v]);
}
else
{
low[u] = min(low[u], dfn[v]);
}
}
if(dfn[u] == low[u])
{
do
{
v = sta.top();
Is[v] = ;
sta.pop();
block[v] = cnt;
}while(u!=v);
cnt++;
}
} int main()
{
int a, b;
while(scanf("%d %d", &n, &m)!=EOF)
{
Init();
while(m--)
{
scanf("%d %d", &a, &b);
G[a].push_back(b);
G[b].push_back(a);
}
for(int i=; i<=n; i++)
if(!dfn[i])
Tarjan(i,-);
for(int i=; i<=n; i++)
{
int v = f[i];
if(v == -)
{
continue;
}
if(block[i] != block[v])
{
du[block[i] ]++;
du[block[v] ]++;
}
}
int ans = ;
for(int i=; i<cnt; i++)
{
if(du[i]==)
ans++;
}
printf("%d\n",(ans+)/); }
return ;
}