NOIP2017赛前模拟 Graph (2017.10.24)
2017-10-25 16:10
489 查看
题意:
给定一个无向图,求最少加多少条边,使得整个图任意两点之间都存在两条及以上的路径。
题解:
作为考试的第一题,据凯爷说,是一道板子题,好像也确实是这样。
首先可以发现,一个边双连通分量中题意肯定成立,所以我们先把一个边双缩成一个点;
然后整张图变成了一棵树,这时候,只要花几个图,就可发现答案为:ans=(度数为1的点的数量+1)/2 ; 如果是在树上找叶子节点,还要判断一下根节点的度数是否为1
给定一个无向图,求最少加多少条边,使得整个图任意两点之间都存在两条及以上的路径。
题解:
作为考试的第一题,据凯爷说,是一道板子题,好像也确实是这样。
首先可以发现,一个边双连通分量中题意肯定成立,所以我们先把一个边双缩成一个点;
然后整张图变成了一棵树,这时候,只要花几个图,就可发现答案为: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; }
相关文章推荐
- 【NOIP2017提高A组模拟10.10】Graph
- NOIP2017赛前模拟 (2017.10.17)考试总结
- NOIP2017赛前模拟(2017.10.20)
- NOIP2017赛前模拟 Table(双向链表)
- NOIP2017赛前模拟 分玩具
- NOIP2017赛前模拟(2017.10.31)考试总结
- NOIP2017赛前模拟 字符串(AC自动机)
- NOIP2017赛前模拟 纸袋(并查集)
- 2017.7.13 NOIP2017赛前模拟考试总结
- NOIP2017赛前模拟 STAR (合理证明复杂度)
- NOIP2017赛前模拟(2017.10.19)
- NOIP2017 赛前模拟(2017.10.30)考试总结
- NOIP2017赛前模拟(2017.10.23)
- NOIP2017赛前模拟(2017.10.20)Matrix (类似轮廓线DP)
- JZOJ 5236. 【NOIP2017模拟8.7A组】利普希茨
- JZOJ 4909. 【NOIP2017模拟12.3】李电下棋
- JZOJ.5329【NOIP2017模拟8.22】时间机器
- 【NOIP2017提高A组模拟8.22】时间机器
- 【NOIP2017提高A组模拟8.25】影子
- MSDN学习DirectShow——第四章 使用DirectShow 第一节 用graphedit模拟创建Graph