您的位置:首页 > 编程语言 > Go语言

poj 2762 Going from u to v or from v to u?(tarjan+拓扑排序)

2014-08-17 11:30 363 查看
Going from u to v or from v to u?

Time Limit: 2000MSMemory Limit: 65536K
Total Submissions: 14488Accepted: 3812
Description

In order to make their sons brave, Jiajia and Wind take them to a big cave. The cave has n rooms, and one-way corridors connecting some rooms. Each time, Wind choose two rooms x and y, and ask one of their little sons go from one to the other. The son can either
go from x to y, or from y to x. Wind promised that her tasks are all possible, but she actually doesn't know how to decide if a task is possible. To make her life easier, Jiajia decided to choose a cave in which every pair of rooms is a possible task. Given
a cave, can you tell Jiajia whether Wind can randomly choose two rooms without worrying about anything?
Input

The first line contains a single integer T, the number of test cases. And followed T cases.

The first line for each case contains two integers n, m(0 < n < 1001,m < 6000), the number of rooms and corridors in the cave. The next m lines each contains two integers u and v, indicating that there is a corridor connecting room u and room v directly.

Output

The output should contain T lines. Write 'Yes' if the cave has the property stated above, or 'No' otherwise.
Sample Input
1
3 3
1 2
2 3
3 1

Sample Output
Yes

题意:判断有向图是否任意两点u、v间都存在u到v的路径或v到u的路径?
1、首先将图中的环缩成点,因为环肯定满足条件;
2、缩成点之后,只有是一条链的时候才满足条件,用拓扑排序判断,若同时存在2个或以上的入度为0的点,则不满足条件。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
#include <vector>
#include <queue>
using namespace std;

const int maxn = 1010;
const int maxe = 2*6005;
int n , m;
vector<int> V[maxn];
int degree[maxn];

/////////////////////////////tarjan
struct edge{
int u , v , next;
edge(int a = 0 , int b = 0 , int c = 0){
u = a , v = b , next = c;
}
}tarjan_e[maxe];
int tarjan_low[maxn] , tarjan_dfn[maxn] , tarjan_vis[maxn] , tarjan_block[maxn] , tarjan_head[maxn];//tarjan_block值相同即属于同一个环
int tarjan_order , tarjan_b , tarjan_cnt;
stack<int> tarjan_stack;

void tarjan_add(int u , int v){
tarjan_e[tarjan_cnt] = edge(u , v , tarjan_head[u]);
tarjan_head[u] = tarjan_cnt++;
}

void tarjan_init(){
for(int i = 0; i < maxn; i++){
tarjan_low[i] = 0;
tarjan_dfn[i] = 0;
tarjan_vis[i] = 0;
tarjan_block[i] = 0;
tarjan_head[i] = -1;
}
tarjan_b = 1;
tarjan_order = 1;
tarjan_cnt = 0;
while(!tarjan_stack.empty()) tarjan_stack.pop();
}

void tarjan(int u){
tarjan_low[u] = tarjan_order;
tarjan_dfn[u] = tarjan_order++;
tarjan_vis[u] = 1;
tarjan_stack.push(u);
for(int i = tarjan_head[u]; i != -1; i = tarjan_e[i].next){
int v = tarjan_e[i].v;
if(!tarjan_dfn[v]){
tarjan(v);
tarjan_low[u] = min(tarjan_low[u] , tarjan_low[v]);
}else if(tarjan_vis[v]) tarjan_low[u] = min(tarjan_low[u] , tarjan_dfn[v]);
}
if(tarjan_low[u] == tarjan_dfn[u]){
int top;
do{
top = tarjan_stack.top();
tarjan_stack.pop();
tarjan_vis[top] = 0;
tarjan_block[top] = tarjan_b;
}while(top != u);
tarjan_b++;
}
}
/////////////////////////////////

void initial(){
tarjan_init();
for(int i = 0; i < maxn; i++){
V[i].clear();
degree[i] = 0;
}
}

void readcase(){
scanf("%d%d" , &n , &m);
int u , v;
for(int i = 0; i < m; i++){
scanf("%d%d" , &u , &v);
tarjan_add(u , v);
}
}

void computing(){
for(int i = 1; i <= n; i++){
if(!tarjan_dfn[i]) tarjan(i);
}
for(int i = 0; i < tarjan_cnt; i++){
int u = tarjan_e[i].u , v = tarjan_e[i].v;
if(tarjan_block[u] != tarjan_block[v]){
//cout << u << " " << v << endl;
degree[tarjan_block[v]]++;
V[tarjan_block[u]].push_back(tarjan_block[v]);
}
}
queue<int> q;
for(int i = 1; i < tarjan_b; i++) if(degree[i] == 0) q.push(i);
while(!q.empty()){
if(q.size() > 1){
printf("No\n");
return;
}
int f = q.front();
q.pop();
for(int i = 0; i < V[f].size(); i++){
degree[V[f][i]]--;
if(degree[V[f][i]] == 0) q.push(degree[V[f][i]]);
}
}
printf("Yes\n");
}

int main(){
int T;
scanf("%d" , &T);
while(T--){
initial();
readcase();
computing();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: