题目:http://poj.org/problem?id=3352
题意:一个连通的无向图,至少需要添加多少条边才能变成边双连通的。
分析:Tarjan缩点之后是一棵树,最终的答案就是树中的叶子节点的数量加1除以2。
题目:http://poj.org/problem?id=3352
题意:一个连通的无向图,至少需要添加多少条边才能变成边双连通的。
分析:Tarjan缩点之后是一棵树,最终的答案就是树中的叶子节点的数量加1除以2。
#define pb push_back
const int maxn(5+1000);
int n,m;
vector<int>adj[maxn];
int indd,dfn[maxn],low[maxn];
int sta[maxn],numsta;
int id[maxn],numid;
void dfsAA(int a,int fax)
{
dfn[a] = low[a] = ++indd;
sta[++numsta] = a;
int s,f,b,fg=0;
for(s=adj[a].size(),f=0; f < s; f++)
{
b = adj[a].at(f);
if(b != fax)
{
if(!dfn[b])
{
dfsAA(b,a);
low[a] = min(low[a], low[b]);
}
else
low[a] = min(low[a], dfn[b]);
}
else
{
if(!fg)
fg = 1;
else
low[a] = min(low[a], low[b]);
}
}
if(dfn[a] == low[a])
{
numid++;
do
{
b = sta[numsta--];
id[b] = numid;
}while(b != a);
}
}
void Tarjan()
{
indd = numsta = numid = 0;
memset(dfn, 0, sizeof dfn);
for(int e=1; e <= n; e++)
if(!dfn[e])
dfsAA(e, -1);
}
int du[maxn];
int cyh()
{
Tarjan();
memset(du, 0, sizeof du);
int e,s,f,b,ans=0;
for(e=1; e <= n; e++)
{
for(s=adj[e].size(),f=0; f < s; f++)
{
b = adj[e].at(f);
if(id[e] != id[b])
du[id[e]]++; ///notice!!
}
}
for(e=1; e <= numid; e++)
ans += (du[e]==1);
return (ans+1)>>1;
}
int main()
{
int e,a,b;
while(cin>>n>>m)
{
for(e=1; e <= n; e++)
adj[e].clear();
while(m--)
{
scanf("%d %d", &a,&b);
adj[a].pb(b), adj[b].pb(a);
}
printf("%d\n", cyh() );
}
return 0;
}