您的位置:首页 > 其它

[NOIP模拟][双连通分量]建设图

2017-10-24 16:18 253 查看
样例输入:

7 7

1 2

2 3

3 4

2 5

4 5

5 6

5 7

样例输入:

2

题目分析:

题目说要使得任何一条道路损坏后,任意两个城市也可以相互到达,这不就是双连通分量的定义吗,所以这道题就是要我们把原图加边加成一个双连通。再考虑原图,它可能含有一些双连通分量,这些双连通分量内部已经符合要求,只是与外面的点还不符合要求。那么可以先缩点,原图就成为了一棵树(题目保证原有道路可以使得所有城市连到)。于是问题转化为加最少的边将一棵树变成双连通的。通过画图发现,其实加的边数等于叶子节点数+1除以2。结论解释:叶子节点数是指那些连边个数为1的点;除法当然是指计算机int除法。注意,画图连边的方法,应该是将最左边的叶子节点和最右边的叶子节点相连,然后次左和次右连~~~,这样才是最优的。最后如何求叶子节点数,你可以dfs(注意根节点有可能就是一个叶子节点,并且有可能原图已经双连通了),也可以直接就统计缩点后那些点连的双连通分量外的边的个数。

附代码:

#include<iostream>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cstdio>
#include<ctime>
#include<cmath>
#include<cctype>
#include<iomanip>
#include<algorithm>
#include<queue>
using namespace std;

const int N=1e5+100;
const int M=2e5+100;
int tot,first
,nxt[M*2],to[M*2],times,top,cnt,pd
,dfn
,low
,po;
int ans,sum,stack
,n,m,maxnum,num
;
bool flag
;

int readint()
{
char ch;int i=0,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') {ch=getchar();f=-1;}
for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<3)+(i<<1)+ch-'0';
ae3e
return i*f;
}

void create(int x,int y)
{
tot++;
nxt[tot]=first[x];
first[x]=tot;
to[tot]=y;
}

void dfs_tarjan(int u,int from)
{
times++;
dfn[u]=times;
low[u]=times;
stack[top++]=u;
for(int e=first[u];e;e=nxt[e])
{
int v=to[e];
if(dfn[v]==0)
{
dfs_tarjan(v,e);
low[u]=min(low[u],low[v]);
}
else
if((e^1)!=from) low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
cnt++;
while(top>=1&&stack[top]!=u)
{
top--;
pd[stack[top]]=cnt;//缩点
}
}
}

int main()
{
freopen("graph.in","r",stdin);
freopen("graph.out","w",stdout);

int x,y;
n=readint();m=readint();
tot=1;
for(int i=1;i<=m;i++)
{
x=readint();y=readint();
create(x,y);
create(y,x);
}
dfs_tarjan(1,0);//tarjan求双连通
tot=0;
for(int i=1;i<=n;i++)
{
for(int e=first[i];e;e=nxt[e])
{
int v=to[e];
if(pd[v]!=pd[i]&&flag[v]==false)//记录缩点后的点连的边数
{
num[pd[i]]++;
num[pd[v]]++;
}
}
flag[i]=true;
}
for(int i=1;i<=cnt;i++)
if(num[i]==1) sum++;//统计叶子节点个数
if(sum%2==1) ans=sum/2+1;
else ans=sum/2;//其实偶数可以和奇数合成一步,+1对于偶数不影响答案
printf("%d",ans);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: