Going from u to v or from v to u?
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 14488 | Accepted: 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.
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;
}