題目大意
一個無向圖,把它變成邊雙連通圖,求出至少要加多少條邊。
n<=100000,m<=500000
時間限制 1s
空間限制 256M
解題思路
比較裸的模型,先縮環成樹,再求出葉子節點個數,根節點需要特判。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100000+6
#define fr(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
struct poi
{
int x;
poi *nex;
} *a[maxn],*b[maxn];
int i,n,m,x,y,z,tot,top,col,ans,d[maxn],fa[maxn],pos[maxn],dfn[maxn],low[maxn];
bool kan[maxn];
void link(int x,int y)
{
poi *p=new poi;
p->x=y;
p->nex=a[x];
a[x]=p;
return;
}
void linkk(int x,int y)
{
poi *p=new poi;
p->x=y;
p->nex=b[x];
b[x]=p;
return;
}
void tarjan(int x)
{
poi *p=new poi;
dfn[x]=low[x]=++tot;
d[++top]=x;
kan[x]=1;
for(p=a[x];p;p=p->nex)
if (!dfn[p->x])
{
fa[p->x]=x;
tarjan(p->x);
low[x]=min(low[x],low[p->x]);
} else if (kan[p->x] && p->x!=fa[x])
low[x]=min(low[x],dfn[p->x]);
if (dfn[x]==low[x])
{
int t=0;
++col;
while (d[top]!=x)
{
kan[d[top]]=0;
pos[d[top]]=col;
++t,--top;
}
kan[d[top]]=0;
pos[d[top]]=col;
++t,--top;
}
return;
}
void dfs(int x)
{
int cai=0;
kan[x]=1;
poi *p=new poi;
for(p=b[x];p;p=p->nex)
if (p->x!=fa[x] && !kan[p->x])
{
cai++;
fa[p->x]=x;
dfs(p->x);
}
if (x!=1 && !cai || x==1 && cai==1) ans++;
return;
}
int main()
{
scanf("%d%d",&n,&m);
fr(i,1,m)
{
scanf("%d%d",&x,&y);
link(x,y),link(y,x);
}
tarjan(1);
poi *p=new poi;
fr(i,1,n)
{
for(p=a[i];p;p=p->nex)
if (pos[p->x]!=pos[i])
{
linkk(pos[p->x],pos[i]);
linkk(pos[i],pos[p->x]);
}
}
memset(fa,0,sizeof(fa));
memset(kan,0,sizeof(kan));
dfs(1);
if (ans&1) ans=ans/2+1;
else ans/=2;
printf("%d\n",ans);
return 0;
}