poj2762 强连通+拓扑序
2015-09-10 14:17
302 查看
题意:有 n 个房间,不同房间之间有单向通道,问是否任意两个房间 A 、B 都可以从 A 到 B 或从 B 到 A(有一条有就可以)。
在这题中,如果一些点是在同一个强连通分量中,那么这些点肯定能够相互到达,并且如果其他的点到达这里的任意一点,也就可以到达强连通分量中的所有点,所以首先需要对这题进行缩点。缩点之后图中就不存在环了,这时需要所有点间都至少有一条路,所以其实剩下了一条长链,并且是单向的,如果有双向的边就会被缩点,如果是数型图的话那么一个节点的多个子树就不能互相到达,所以一定是一条单向的长链,因此只要拓扑序判断就行,也可以对于这个图判段是否只有一点入度为1,一点出度为1,剩余点出入度都为1就行。
View Code
在这题中,如果一些点是在同一个强连通分量中,那么这些点肯定能够相互到达,并且如果其他的点到达这里的任意一点,也就可以到达强连通分量中的所有点,所以首先需要对这题进行缩点。缩点之后图中就不存在环了,这时需要所有点间都至少有一条路,所以其实剩下了一条长链,并且是单向的,如果有双向的边就会被缩点,如果是数型图的话那么一个节点的多个子树就不能互相到达,所以一定是一条单向的长链,因此只要拓扑序判断就行,也可以对于这个图判段是否只有一点入度为1,一点出度为1,剩余点出入度都为1就行。
#include<stdio.h> #include<string.h> #include<stack> #include<queue> using namespace std; const int maxn=1005; const int maxm=6005; int head[2][maxn],point[2][maxm],nxt[2][maxm],size[2]; int n,t,scccnt; int id[maxn],stx[maxn],low[maxn],scc[maxn]; stack<int>S; void init(){ memset(head,-1,sizeof(head)); size[0]=size[1]=0; memset(id,0,sizeof(head)); } void add(int a,int b,int c=0){ point[c][size[c]]=b; nxt[c][size[c]]=head[c][a]; head[c][a]=size[c]++; if(c)id[b]++; } void dfs(int s){ stx[s]=low[s]=++t; S.push(s); for(int i=head[0][s];~i;i=nxt[0][i]){ int j=point[0][i]; if(!stx[j]){ dfs(j); low[s]=min(low[s],low[j]); } else if(!scc[j]){ low[s]=min(low[s],stx[j]); } } if(low[s]==stx[s]){ scccnt++; while(1){ int u=S.top();S.pop(); scc[u]=scccnt; if(s==u)break; } } } void setscc(){ memset(stx,0,sizeof(stx)); memset(scc,0,sizeof(scc)); t=0; scccnt=0; for(int i=1;i<=n;++i)if(!stx[i])dfs(i); for(int i=1;i<=n;++i){ for(int j=head[0][i];~j;j=nxt[0][j]){ int k=point[0][j]; if(scc[i]!=scc[k]){ add(scc[i],scc[k],1); } } } } bool topo(){ queue<int>q; int cnt=0; for(int i=1;i<=scccnt;++i)if(!id[i])q.push(i); while(!q.empty()){ int u=q.front(); q.pop(); if(!q.empty())return 0; cnt++; for(int i=head[1][u];~i;i=nxt[1][i]){ int j=point[1][i]; id[j]--; if(!id[j])q.push(j); } } if(cnt==scccnt)return 1; return 0; } int main(){ int T; scanf("%d",&T); while(T--){ int m; scanf("%d%d",&n,&m); init(); while(m--){ int a,b; scanf("%d%d",&a,&b); add(a,b); } setscc(); if(topo())printf("Yes\n"); else printf("No\n"); } return 0; }
View Code
相关文章推荐
- linux SVN常见问题解决
- Jenkins+maven+pmd对java代码进行静态代码分析
- Java中的final关键字
- Oracle用户创建及权限设置
- 悲观锁与乐观锁
- C++ 排序
- 配置MST实现负载均衡
- Vin2008 X64安装.Net Framework1.1
- ITRON系统
- nginx上设置禁止通过ip访问服务器,只能通过域名访问
- lintcode-删除数字-182
- Web browser的发展演变
- Java EE实用开发指南:基于Weblogic+EJB3+Struts2+Hibernate+Spring 高洪岩 配套源码下载地址
- 网站推广新趋向:以词带量,思路至上
- MySQL技术之旅-慢查询作用、解析工具
- Python之GDAL配置
- mstsc保存用户名和密码,实现自动登录远程桌面
- Android studio 中使用GeenDao
- Sysbench简介和测试
- 三张图看遍Linux性能监控、测试、优化工具