您的位置:首页 > 其它

NOIP2017赛前模拟 Graph (2017.10.24)

2017-10-25 16:10 489 查看
题意:

 给定一个无向图,求最少加多少条边,使得整个图任意两点之间都存在两条及以上的路径。

题解:

 作为考试的第一题,据凯爷说,是一道板子题,好像也确实是这样。

 首先可以发现,一个边双连通分量中题意肯定成立,所以我们先把一个边双缩成一个点;

 然后整张图变成了一棵树,这时候,只要花几个图,就可发现答案为:ans=(度数为1的点的数量+1)/2 ; 如果是在树上找叶子节点,还要判断一下根节点的度数是否为1

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<cctype>
#include<string>
using namespace std;
const int N = 100005;
const int M = 200005;
int n,m,x,y,num,ans,pointnum,top,tra_sort,tot=1;
int head
,first
,son
,to[M*2],nxt[M*2];
int low
,dfn
,stack
,belong
;
bool vis
,instack
;
struct node{
int to,nxt;
bool vis;
}edge[M*2];
inline int Readint(){
int i=0,f=1;char c;
for(c=getchar();!isdigit(c) && c!='-';c=getchar());
if(c=='-') f=-1,c=getchar();
for(;isdigit(c);c=getchar()) i=(i<<1)+(i<<3)+c-'0';
return i*f;
}
inline void add(int x,int y){
edge[++tot].to=y;
edge[tot].nxt=first[x];
first[x]=tot;
}
inline void create(int x,int y){
nxt[++tot]=head[x];
head[x]=tot;
to[tot]=y;
}
inline void tra(int x){
low[x]=dfn[x]=++tra_sort;
stack[++top]=x,instack[x]=true;
for(int i=first[x];i;i=edge[i].nxt){
if(!edge[i].vis){
edge[i].vis=true;
edge[i^1].vis=true;
int v=edge[i].to;
if(!dfn[v]){
tra(v);
low[x]=min(low[x],low[v]);
}
else if(instack[v]) low[x]=min(low[x],dfn[v]);
}
}
if(low[x]==dfn[x]){
pointnum++;
int j=-1;
while(j!=x){
j=stack[top--];
belong[j]=pointnum;
}
}
}
inline void DFS(int x){
vis[x]=true;
bool bz=false;
for(int i=head[x];i;i=nxt[i]){
if(!vis[to[i]]){
vis[to[i]]=true;
son[x]++;
DFS(to[i]);
bz=true;
}
}
if(bz==false) num++;
}
int main(){
//  freopen("graph.in","r",stdin);
//  freopen("graph.out","w",stdout);

n=Readint(),m=Readint();
for(int i=1;i<=m;i++){
x=Readint(),y=Readint();
add(x,y); add(y,x);
}
for(int i=1;i<=n;i++) if(!dfn[i]) tra(i);
tot=0;
for(int i=1;i<=n;i++){
for(int e=first[i];e;e=edge[e].nxt){
if(belong[i]!=belong[edge[e].to]){
create(belong[i],belong[edge[e].to]);
}
}
}
DFS(1);
if(pointnum==1) cout<<"0";
else{
if(son[1]%2==0){
ans=(num/2)+((num%2)==0 ? 0 : 1);
}
else{
num++;
ans=(num/2)+((num%2)==0 ? 0 : 1);
}
cout<<ans;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: