poj2762 Going from u to v or from v to u? 强连通分量 + 拓扑排序
2016-04-27 21:42
579 查看
题目:http://poj.org/problem?id=2762
题意:给定两个数n,m,代表n个点,有m条有向边。对于任意两个点u,v,能不能从u到v或者从v到u,是就输出Yes,否则No
思路:显然强连通分量内的任意两点是互通的,于是强连通分量分解缩点,对于缩点后建成的图,要保证是一条链式的结构,不能有分叉,因为分叉上的点必然不能相通,可以用拓扑排序,保证每次入队的入度为0的点为1个,那么满足此条件的必然是链式结构的图
总结:这个题wa好几次,怪我脑残,在判断链式结构时居然用有一个点出度0,其余点出度为1来判断,后来找到反例
3 3
1 2
2 3
1 3
用dfs去判断链式结构也是可行的。
这道题写的挺搓的,二次建图时没用链式前向星,用了vector。。。
题意:给定两个数n,m,代表n个点,有m条有向边。对于任意两个点u,v,能不能从u到v或者从v到u,是就输出Yes,否则No
思路:显然强连通分量内的任意两点是互通的,于是强连通分量分解缩点,对于缩点后建成的图,要保证是一条链式的结构,不能有分叉,因为分叉上的点必然不能相通,可以用拓扑排序,保证每次入队的入度为0的点为1个,那么满足此条件的必然是链式结构的图
总结:这个题wa好几次,怪我脑残,在判断链式结构时居然用有一个点出度0,其余点出度为1来判断,后来找到反例
3 3
1 2
2 3
1 3
用dfs去判断链式结构也是可行的。
这道题写的挺搓的,二次建图时没用链式前向星,用了vector。。。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <queue> using namespace std; const int N = 10010; int n, m; struct edge { int to, next; } G[N*10]; int dfn , low , st , scc , head ; bool vis ; int cnt, index, top, num; void init() { memset(head, -1, sizeof head); memset(dfn, -1, sizeof dfn); memset(vis, 0, sizeof vis); cnt = index = top = num = 0; } void add_edge(int v, int u) { G[cnt].to = u; G[cnt].next = head[v]; head[v] = cnt++; } void tarjan(int v) { dfn[v] = low[v] = index++; vis[v] = true; st[top++] = v; int u; for(int i = head[v]; i != -1; i = G[i].next) { u = G[i].to; if(dfn[u] == -1) { tarjan(u); low[v] = min(low[v], low[u]); } else if(vis[u]) low[v] = min(low[v], dfn[u]); } if(dfn[v] == low[v]) { num++; do { u = st[--top]; vis[u] = false; scc[u] = num; } while(u != v); } } bool toposort(vector<int> graph[], int indegree[])/*拓扑排序判断链式结构*/ { queue<int> que; for(int i = 1; i <= num; i++) if(indegree[i] == 0) que.push(i); if(que.size() > 1) return false; while(! que.empty()) { int v = que.front(); que.pop(); int len = graph[v].size(); int tmp = 0; for(int i = 0; i < len; i++) { if(--indegree[graph[v][i]] == 0) que.push(graph[v][i]), tmp++; } if(tmp > 1) return false; } return true; } void slove() { for(int i = 1; i <= n; i++) if(dfn[i] == -1) tarjan(i); int indegree ;/*缩点重新建图*/ vector<int> graph ; memset(indegree, 0, sizeof indegree); for(int i = 1; i <= n; i++) for(int j = head[i]; j != -1; j = G[j].next) if(scc[i] != scc[G[j].to]) { indegree[scc[G[j].to]]++; graph[scc[i]].push_back(scc[G[j].to]); } if(toposort(graph, indegree)) printf("Yes\n"); else printf("No\n"); } int main() { int t, a, b; scanf("%d", &t); while(t--) { scanf("%d%d", &n, &m); init(); for(int i = 0; i < m; i++) { scanf("%d%d", &a, &b); add_edge(a, b); } slove(); } return 0; }
相关文章推荐
- poj 3107 Godfather(树形DP)
- warshall's algorithm
- Django表单CSRF验证失败解决方案
- HDU 2401 Baskets of Gold Coins(数学题)
- LightOJ 1030 Discovering Gold
- Mongoose(二):快速开始
- Mongoose(一):为什么选择Mongoose
- POJ 3767 I Wanna Go Home(最短路/Floyd)
- Django单元测试简明实践
- JFinal与Mogodb集成的问题
- golang 中的内嵌(embeded)
- Django学习笔记(一)
- Google短网址的API
- zygote进程
- Django error信息邮件通知功能配置部署
- Django “no such table: django_session”的解决办法
- beego的文档生成
- flex写的下载器在Google浏览器下有些文件下载不了如exe文件
- SEO搜索优化傻脸了:Google放弃PageRank
- DashgoD1下位机使用说明