POJ 2762 Going from u to v or from v to u? (强连通分量缩点+拓扑排序)
2016-03-13 20:19
316 查看
题目链接:http://poj.org/problem?id=2762
题意是 有t组样例,n个点m条有向边,取任意两个点u和v,问u能不能到v 或者v能不能到u,要是可以就输出Yes,否则输出No。注意一点,条件是或者!所以不是判断双连通图的问题。
我一开始没看到'or'这个条件,所以直接tarjan判断是否只有一个强连通分量,果断WA。
所以需要给原图缩点,用tarjan把图变成一个有向无环图,要是只有一个scc,那就直接输出Yes。那接下来讨论多个scc,要是新图中有两个及以上的点的入度为0,则这些点都不能相互到达,所以输出No,所以我们找到唯一一个入度为0的点作为root,然后从这个点来拓扑排序,出队入队的过程肯定是一进一出的,所以根据过程来判断是否输出Yes和No。
题意是 有t组样例,n个点m条有向边,取任意两个点u和v,问u能不能到v 或者v能不能到u,要是可以就输出Yes,否则输出No。注意一点,条件是或者!所以不是判断双连通图的问题。
我一开始没看到'or'这个条件,所以直接tarjan判断是否只有一个强连通分量,果断WA。
所以需要给原图缩点,用tarjan把图变成一个有向无环图,要是只有一个scc,那就直接输出Yes。那接下来讨论多个scc,要是新图中有两个及以上的点的入度为0,则这些点都不能相互到达,所以输出No,所以我们找到唯一一个入度为0的点作为root,然后从这个点来拓扑排序,出队入队的过程肯定是一进一出的,所以根据过程来判断是否输出Yes和No。
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace std; const int MAXN = 1005; struct data { int next , to; }edge[MAXN * 6]; int head[MAXN] , st[MAXN] , low[MAXN] , dfn[MAXN] , block[MAXN] , du[MAXN]; int top , ord , sccnum , cont; bool instack[MAXN]; vector <int> G[MAXN]; inline void add(int u , int v) { edge[cont].next = head[u]; edge[cont].to = v; head[u] = cont++; } void init() { memset(head , -1 , sizeof(head)); memset(dfn , 0 , sizeof(dfn)); memset(du , 0 , sizeof(du)); memset(instack , false , sizeof(instack)); top = sccnum = ord = cont = 0; } void tarjan(int u) { low[u] = dfn[u] = ++ord; st[++top] = u; instack[u] = true; for(int i = head[u] ; ~i ; i = edge[i].next) { int v = edge[i].to; if(!dfn[v]) { tarjan(v); low[u] = min(low[u] , low[v]); } else if(instack[v]) { low[u] = min(low[u] , low[v]); } } if(low[u] == dfn[u]) { int v; sccnum++; do { v = st[top--]; instack[v] = false; block[v] = sccnum; }while(u != v); } } void top_sort() { queue <int> que; while(!que.empty()) { que.pop(); } cont = 0; for(int i = 1 ; i <= sccnum ; i++) { if(!du[i]) { que.push(i); cont++; } } if(cont > 1) { printf("No\n"); return ; } while(!que.empty()) { int temp = que.front() , cnt = 0; que.pop(); for(int i = 0 ; i < G[temp].size() ; i++) { du[G[temp][i]]--; if(!du[G[temp][i]]) { cnt++; cont++; que.push(G[temp][i]); } } if(cnt > 1) { printf("No\n"); return ; } } if(cont != sccnum) { printf("No\n"); } else { printf("Yes\n"); } } int main() { int t , n , m , u , v; scanf("%d" , &t); while(t--) { scanf("%d %d" , &n , &m); init(); for(int i = 0 ; i < m ; i++) { scanf("%d %d" , &u , &v); add(u , v); } for(int i = 1 ; i <= n ; i++) { G[i].clear(); if(!dfn[i]) tarjan(i); } if(sccnum == 1) { printf("Yes\n"); continue; } for(int u = 1 ; u <= n ; u++) { for(int i = head[u] ; ~i ; i = edge[i].next) { int v = edge[i].to; if(block[u] != block[v]) { du[block[v]]++; G[block[u]].push_back(block[v]); } } } top_sort(); } }
相关文章推荐
- 我与小娜(35):AlphaGo第四局为何输了?
- Go语言并发之美
- Machine Learning - Neural Networks for Multi-class Classification
- 除百度、Google外其他蜘蛛IP封锁脚本
- HibernateTemplate、HibernateDaoSupport两种方法实现增删改查Good
- 【大雾】关于mongoose的model的小问题
- 【大雾】mongoose中createConnection和connect的大坑!
- The 8th Zhejiang Provincial Collegiate Programming Contest-> Kagome Kagome
- 李世石首胜谷歌AlphaGo
- 李世石首胜谷歌AlphaGo
- uva11292 The Dragon of Loowater
- ubuntu14.04 and ros indigo install kinect driver--16
- Django 学习笔记二
- Golang websocket使用方法
- django中的分页
- Django 学习笔记一
- 一些重要的算法The Most Important Algorithms
- Django实战教程 分页列表
- Django分页的基本实现办法
- Django实战(20):分页(Pagination)