题目链接:http://poj.org/problem?id=3352
看这题的时候已经知道了是用tarjan算法,不过还是不知道要加几条边,百度了之后看到了统计出树中度为1的节点的个数,即为叶节点的个数,记为leaf。则至少在树上添加(leaf+1)/2条边,就能使树达到边二连通,所以至少添加的边数就是(leaf+1)/2。
不过个人感觉百度首页的题解代码似乎都没我自己写的简洁,所以特此开个贴记录一下自己的小模板,代码注释这次就懒得打了,命名这些也是按照算法模板化命名的,学过这个算法的应该都能看得懂,没学过的就百度tarjan算法去学吧,在此不做复述了
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
vector<int> G[1005];
int dfn[1005],low[1005]={0},degree[1005]={0};
int index;
void tarjan(int u,int fa)
{
dfn[u]=low[u]=++index;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(!dfn[v])
{
tarjan(v,u);
low[u]=min(low[u],low[v]);
}
else if(v!=fa)
{
low[u]=min(low[u],dfn[v]);
}
}
}
int main()
{
int n,m;
while(scanf("%d %d",&n,&m)!=EOF)
{
memset(dfn,0,sizeof(int)*1005);
memset(low,0,sizeof(int)*1005);
memset(degree,0,sizeof(int)*1005);
index=0;
for(int i=0;i<m;i++)
{
int a,b;
scanf("%d %d",&a,&b);
G[a].push_back(b);
G[b].push_back(a);
}
tarjan(1,-1);
for(int i=1;i<=n;i++)
{
for(int j=0;j<G[i].size();j++)
{
if(low[i]!=low[G[i][j]])
degree[low[i]]++;
}
}
int ans=0;
for(int i=1;i<=n;i++)
{
if(degree[i]==1)
ans++;
}
printf("%d\n",(ans+1)/2);
}
return 0;
}