题意:给出一个无向联通图,求最少添加几条边让图是双联通图。
思路:先Tarjan缩点,(求出度数为1的双联通分量的个数+1)/2;
#include<stdio.h>
#include<string.h>
const int N=1100;
int dep[N],dfs[N],low[N],ans,idx,head[N],num;
struct edge
{
int st,ed,next;
}e[N*100];
void addedge(int x,int y)
{
e[num].st=x;e[num].ed=y;e[num].next=head[x];head[x]=num++;
e[num].st=y;e[num].ed=x;e[num].next=head[y];head[y]=num++;
}
void Tarjan(int u,int id)
{
int i,v;
dfs[u]=low[u]=++idx;
for(i=head[u];i!=-1;i=e[i].next)
{
if(i==(id^1))continue;
v=e[i].ed;
if(dfs[v]==-1)
{
Tarjan(v,i);
low[u]=low[u]>low[v]?low[v]:low[u];
}
else low[u]=low[u]>dfs[v]?dfs[v]:low[u];
}
}
int main()
{
int i,n,m,x,y,sum;
while(scanf("%d%d",&n,&m)!=-1)
{
memset(head,-1,sizeof(head));
num=0;
for(i=0;i<m;i++)
{
scanf("%d%d",&x,&y);
addedge(x,y);
}
memset(dfs,-1,sizeof(dfs));
ans=idx=0;
Tarjan(1,-1);
memset(dep,0,sizeof(dep));
for(i=0;i<num;i+=2)
{
x=low[e[i].st];
y=low[e[i].ed];
if(x==y)continue;
dep[x]++;
dep[y]++;
}
sum=0;
for(i=1;i<=idx;i++)
{
if(dep[i]==1)
sum++;
}
printf("%d\n",(sum+1)/2);
}
return 0;
}