[NOIP2017模拟]建设图
2017-10-24 15:56
330 查看
2017.10.24 T1 2007
样例数据
输入
7 7
1 2
2 3
3 4
2 5
4 5
5 6
5 7
输出
2
分析:看到这道题我就知道它是个tarjan了,只是不知道求什么,看样例我以为是求割点,出其他数据发现不对;然后觉得也许是割边,发现也不对;想了半天之后,觉得tarjan剩下的就只有双连通分量了,试了试缩点,嗯,变成了一棵树,于是我就又建了几棵树,发现需要(叶子节点+1)/2条边就可以把整棵树变成双连通图(根节点如果只连了一条边也算是叶子),然后兴冲冲地打好了这道题,还检查了很久,觉得这道题就是今天的得分支柱了。
然而,今天在linux下评测,我的tarjan多年来记dfn和low值的都是“index”,在linux中“index”是关键字,直接编译错误,爆0……而在oj上的评测机是windows环境,AC……(其实还少了一个特判,如果整个图都是双连
4000
通的,那最后就只有一个根点,会被判成叶子节点,答案就是(1+1)/2=1,实际上并不需要连边,但是不黑心的wuvin并没有出这样的数据卡我嘿嘿嘿)
结论:一棵树要加边成为双连通图需要加(叶子节点数+1)/2条边(如果根节点只连了一条边也算作叶子节点)。
代码
本题结。
样例数据
输入
7 7
1 2
2 3
3 4
2 5
4 5
5 6
5 7
输出
2
分析:看到这道题我就知道它是个tarjan了,只是不知道求什么,看样例我以为是求割点,出其他数据发现不对;然后觉得也许是割边,发现也不对;想了半天之后,觉得tarjan剩下的就只有双连通分量了,试了试缩点,嗯,变成了一棵树,于是我就又建了几棵树,发现需要(叶子节点+1)/2条边就可以把整棵树变成双连通图(根节点如果只连了一条边也算是叶子),然后兴冲冲地打好了这道题,还检查了很久,觉得这道题就是今天的得分支柱了。
然而,今天在linux下评测,我的tarjan多年来记dfn和low值的都是“index”,在linux中“index”是关键字,直接编译错误,爆0……而在oj上的评测机是windows环境,AC……(其实还少了一个特判,如果整个图都是双连
4000
通的,那最后就只有一个根点,会被判成叶子节点,答案就是(1+1)/2=1,实际上并不需要连边,但是不黑心的wuvin并没有出这样的数据卡我嘿嘿嘿)
结论:一棵树要加边成为双连通图需要加(叶子节点数+1)/2条边(如果根节点只连了一条边也算作叶子节点)。
代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<ctime> #include<cmath> #include<algorithm> #include<cctype> #include<iomanip> #include<queue> #include<set> using namespace std; int getint() { int sum=0,f=1; char ch; for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar()); if(ch=='-') { f=-1; ch=getchar(); } for(;isdigit(ch);ch=getchar()) sum=(sum<<3)+(sum<<1)+ch-48; return sum*f; } const int maxn=100010; const int maxm=200010; int n,m,ans; int tot,first[maxn],nxt[maxm*2],to[maxm*2]; int dep,dfn[maxn],low[maxn],zhan[maxn],top,cnt,slt[maxn]; int num,chudu[maxn]; bool visit[maxn]; void addedge(int x,int y) { tot++; nxt[tot]=first[x]; first[x]=tot; to[tot]=y; tot++; nxt[tot]=first[y]; first[y]=tot; to[tot]=x; } void tarjan(int u,int fro) { dep++;//千万不要再用index了!!! dfn[u]=dep; low[u]=dep; zhan[top]=u; top++; for(int p=first[u];p;p=nxt[p]) { int v=to[p]; if(!dfn[v]) { tarjan(v,p); low[u]=min(low[u],low[v]); } else if((p^1)!=fro) low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u])//把双连通分量缩点 { cnt++; while(zhan[top]!=u) { top--; slt[zhan[top]]=cnt; } } } void dfs(int u) { for(int p=first[u];p;p=nxt[p]) { int v=to[p]; if(!visit[v]) { visit[v]=true; if(slt[v]!=slt[u])//不是同一个连通块所以u的连通块的出度++ chudu[slt[u]]++; dfs(v); } } } int main() { freopen("graph.in","r",stdin); freopen("graph.out","w",stdout); int x,y;tot=1; n=getint(),m=getint(); for(int i=1;i<=m;++i) { x=getint(),y=getint(); addedge(x,y); } tarjan(1,0);//tarjan求双连通分量并缩点 visit[1]=true; dfs(1);//从根开始向深处搜,找到出度为0的点,也就是叶子节点 for(int i=1;i<=cnt;++i) if(chudu[i]==0) num++; if(chudu[slt[1]]==1)//特判一下根节点是不是只连了一条边 num++; if(num==1)//整个图就只有一个点的话 ans=0; else ans=(num+1)/2;//结论 cout<<ans<<'\n'; return 0; }
本题结。
相关文章推荐
- 【jzoj5248】【NOIP2017提高A组模拟8.10】【花花的聚会】【动态规划】【可持久化线段树】
- [JZSC2017]【NOIP2017提高组模拟6.29】总结
- [jzoj5406]【NOIP2017提高A组模拟10.10】Tree
- [NOIP2017模拟]随机图
- [NOIP2017模拟]Fibonacci
- NOIP模拟(10.24)T1 建设图
- [NOIP2017模拟]hello
- jzoj5335 【NOIP2017提高A组模拟8.24】早苗 (递推优化矩乘)
- 降雷皇 【NOIP2017提高组模拟12.10】
- JZOJ5344. 【NOIP2017模拟9.3A组】摘果子
- JZOJ4923. 【NOIP2017提高组模拟12.17】巧克力狂欢
- 【jzoj5346】【NOIP2017提高A组模拟9.5】【NYG的背包】【贪心】
- [JZOJ5390]【NOIP2017提高A组模拟9.26】逗气
- 【NOIP2017练习】溢出(模拟)
- JZOJ5358. 【NOIP2017提高A组模拟9.12】BBQ
- 【JZOJ 5394】【NOIP2017提高A组模拟10.5】Ping
- [NOIP2017模拟]Sequence
- [JZOJ5394]【NOIP2017提高A组模拟10.5】Ping
- [NOIP2017模拟]road
- [NOIP2017模拟]造盒子