Poj2762——有向图缩点+拓扑排序
来源:互联网 发布:帝国cms广告代码 编辑:程序博客网 时间:2024/05/18 03:02
题目链接:
http://poj.org/problem?id=2762
题目大意:
给定一个有向图,问该图是否连通。
有向图连通性的定义:
对于任意两个点u和v,总会存在一条路径从u——v或者是从v——u。
解题思路:
如果是没有环的有向图的话,那么只有当所有的点都在一条链上的时候,图才是连通的。
第1步:求取强连通分量,对有向图进行缩点。建立新图。
第2步:对新图进行拓扑排序。要求每次取点的时候,度数为0的点都只能有一个,这样就能保证新图是连通的。
注意事项:
在题目中用到了STL容器,对容器进行清空的时候,不要使用memset,而应该使用容器本身的清空函数,否则会出现runtime error。
源代码:
#include<stdio.h>#include<iostream>#include<math.h>#include<string.h>#include<string>#include<map>#include<vector>#include<set>#include<queue>#include<algorithm>using namespace std;vector<int> child[1001];vector<int> pre[1001];struct node{ int end_time; int id;}s[1001];struct node1{ int du; vector<int> child;}p[1001];bool cmp(node a,node b){ return a.end_time>b.end_time; //按照结束时间戳进行排序}int vis[1001];int Set[1001]; //每个节点属于哪个强连通分量int n,m,cnt,Time,flag;void dfs1(int now) //第1次dfs按照孩子节点进行排序得到了{ int i,len,kid; len=child[now].size(); for(i=0;i<len;i++) { kid=child[now][i]; if(!vis[kid]) { vis[kid]=1; dfs1(kid); } } s[now].end_time=++Time; s[now].id=now; return;}void dfs2(int now){ int i,len,father; len=pre[now].size(); for(i=0;i<len;i++) { father=pre[now][i]; if(!vis[father]) { vis[father]=1; dfs2(father); } } Set[now]=cnt; return;}void top_sort(){ int i,j,k,t,b,len,child; while(1) //如果每次度为0的点只有一个,那么这种情况就是合法的 { b=0; for(i=1;i<=cnt;i++) { if(p[i].du==0) { t=i; b++; } } if(b==0) { flag=1; break; } if(b!=1) break; p[t].du=-1; len=p[t].child.size(); for(i=0;i<len;i++) { child=p[t].child[i]; p[child].du--; } } return;}int main(){freopen("in.txt","r",stdin);int cs,a,b,i,j,k,t,id,x,y,len;scanf("%d",&cs);while(cs--) { scanf("%d%d",&n,&m); memset(s,0,sizeof(s)); for(i=0;i<=n;i++) { child[i].clear(); pre[i].clear(); } while(m--) { scanf("%d%d",&a,&b); child[a].push_back(b); pre[b].push_back(a); } //dfs1求取时间戳 memset(vis,0,sizeof(vis)); Time=0; for(i=1;i<=n;i++) { if(!vis[i]) { vis[i]=1; dfs1(i); } } sort(s+1,s+1+n,cmp); //dfs2求取强连通分量 memset(vis,0,sizeof(vis)); cnt=0; for(i=1;i<=n;i++) { id=s[i].id; if(!vis[id]) { cnt++; vis[id]=1; dfs2(id); } } //统计每个强连通分量的入度出度以及孩子与父亲之类的关系 memset(p,0,sizeof(p)); for(i=1;i<=n;i++) { x=Set[i]; len=child[i].size(); for(j=0;j<len;j++) { y=child[i][j]; y=Set[y]; //y是x的孩子节点 if(x==y) continue; p[x].child.push_back(y); p[y].du++; } } flag=0; top_sort(); if(flag==1) printf("Yes\n"); else printf("No\n"); }return 0;}
- Poj2762——有向图缩点+拓扑排序
- poj2762 Going from u to v or from v to u? 有向图 强连通分量 拓扑排序
- 数据结构——有向图(拓扑排序算法)
- 有向图的拓扑排序——基于邻接矩阵
- 判断有向图是否存在回路—拓扑排序
- 有向图—拓扑排序,Kosaraju算法
- 有向图--拓扑排序
- poj2762 弱连通 缩点+ 拓扑排序
- 拓扑排序——判断有向图是否存在回路
- 数据结构与算法——有向无环图的拓扑排序C++实现
- 拓扑排序——有向无环图(湖南省第十二届大学生计算机程序设计竞赛 B)
- 图(有向图)的应用——拓扑排序
- 有向图的拓扑排序
- 有向图的拓扑排序
- C#有向图拓扑排序
- 有向图的拓扑排序C++
- 图论-有向图的拓扑排序
- 有向无环图的拓扑排序
- oracle一些常识
- RTL代码风格
- KVM虚拟机和QEMU
- Static synchronized Method
- Android gridview 图标浮出效果
- Poj2762——有向图缩点+拓扑排序
- 大数据:利用相关性的营销
- rmdir()
- NSSortDescriptor(数组排序)
- Quartz任务调度快速入门
- 个人碰到的简单问题处理,慢慢总结
- HDU-1232-畅通工程-最简单并查集问题
- MongoDB的查询
- Bone Collector