poj2762 缩点+topo排序

Going from u to v or from v to u?

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 16486   Accepted: 4386

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

题意:

有一张有向图,然后问对于任意的2个点,是否存在x可以到达y,或者y能够到达x。

思路:

可以先强连通缩点,这样就没有环的情况。然后这样就是一张新的图。也就是相当于在新的图中判断任意2个点能否存在一条路径。这可以用topo排序来解决。如果存在2个点,他们的入度为0,说明这2个点是不能相互到达的。

/*
 * Author:  sweat123
 * Created Time:  2016/6/25 12:33:09
 * File Name: main.cpp
 */
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<string>
#include<vector>
#include<cstdio>
#include<time.h>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 1<<30
#define MOD 1000000007
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pi acos(-1.0)
using namespace std;
const int MAXN = 20000;
struct node{
    int from;
    int to;
    int next;
}edge[MAXN*1000];
int pre[MAXN],vis[MAXN],dfn[MAXN],low[MAXN],n,m,ind;
int f[MAXN],num,k;
stack<int>s;
void add(int x,int y){
    edge[ind].from = x;
    edge[ind].to = y;
    edge[ind].next = pre[x];
    pre[x] = ind ++;
}
void dfs(int rt){
    vis[rt] = 1;
    dfn[rt] = low[rt] = ++k;
    s.push(rt);
    for(int i = pre[rt]; i != -1; i = edge[i].next){
        int t = edge[i].to;
        if(!dfn[t]){
            dfs(t);
            low[rt] = min(low[rt],low[t]);
        } else if(vis[t]){
            low[rt] = min(low[rt],dfn[t]);
        }
    }
    if(low[rt] == dfn[rt]){
        ++ num;
        while(!s.empty()){
            int tp = s.top();
            s.pop();
            vis[tp] = 0;
            f[tp] = num;
            if(tp == rt)break;
        }
    }
}
int x[MAXN],y[MAXN],ans,in[MAXN];
int ok(){
    queue<int>q;
    for(int i = 1; i <= num; i++){
        if(in[i] == 0){
            q.push(i);
        }
    }
    if(q.size() > 1)return 0;
    while(!q.empty()){
        int tp = q.front();
        q.pop();
        for(int i = pre[tp]; i != -1; i = edge[i].next){
            int t = edge[i].to;
            in[t] --;
            if(in[t] == 0){
                q.push(t);
            }
        }
        if(q.size() > 1)return 0;
    }
    return 1;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        ind = 0;
        while(!s.empty())s.pop();
        memset(pre,-1,sizeof(pre));
        for(int i = 1; i <= m; i++){
            scanf("%d%d",&x[i],&y[i]);
            add(x[i],y[i]);
        }
        k = 0;
        num = 0;
        memset(vis,0,sizeof(vis));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(f,0,sizeof(f));
        for(int i = 1; i <= n; i++){
            if(!dfn[i])dfs(i);
        }
        memset(pre,-1,sizeof(pre));
        memset(in,0,sizeof(in));
        int ret = ind;
        for(int i = 0; i < ret; i++){
            int u = f[edge[i].from];
            int v = f[edge[i].to];
            if(u != v){
                add(u,v);
                in[v] ++;
            }
        }
        if(ok()){
            printf("Yes\n");
        } else{
            printf("No\n");
        }
    }
    return 0;
}
时间: 2024-10-13 18:46:16

poj2762 缩点+topo排序的相关文章

POJ 2762判断单联通(强连通缩点+拓扑排序)

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

topo排序完全版

输入数据: 4 61 21 32 33 42 44 2 4 61 21 32 33 42 41 2 topo排序为偏序: 演示:http://www.tyut.edu.cn/kecheng1/site01/suanfayanshi/topological_sort.asp 详细:http://blog.csdn.net/dm_vincent/article/details/7714519 1 #include<stdio.h> 2 #include<queue> 3 #includ

POJ 3114 - Countries in War(强连通分量+缩点+拓扑排序+DAG最短路)

Countries in War Time Limit:1000MS    Memory Limit:65536KB    64bit IO Format:%I64d & %I64u Appoint description: Description In the year 2050, after different attempts of the UN to maintain peace in the world, the third world war broke out. The impor

hiho一下&#183;47 拓扑排序&#183;一(判断是否能够Topo排序)

题意  中文 简单的Topo排序  用vector实现邻接表比较方便 #include <bits/stdc++.h> using namespace std; const int N = 1e5 + 5; vector<int> e[N]; vector<int>::iterator it; int n, m, ideg[N]; bool topo() { int cur; queue<int> q; for(int i = 1; i <= n; +

POJ2762 Going from u to v or from v to u?(强连通缩点+拓扑排序)

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

POJ2762 Going from u to v or from v to u? 强连通分量缩点+拓扑排序

题目链接:https://vjudge.net/contest/295959#problem/I 或者 http://poj.org/problem?id=2762 题意:输入多组样例,输入n个点和m条有向边,问该图中任意两点x, y之间是否满足x可以到y或者y可以到x. 一开始WA的原因是因为没注意到是或者, 如果是并且的话,就是一道简单的强连通分量的题,直接判断整个图是否为一个强连通分量 对于该题, 先用强连通分量进行缩点,简化图.图就变成了DAG,用拓扑排序判断图中点的入度, 图中入度为0

poj 2762 Going from u to v or from v to u?【强连通分量缩点+拓扑排序】

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

[模板]tarjan缩点+拓扑排序

题目:给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次. 题目简述:先tarjan缩点,再从入度为零处进行一次拓扑排序,求最长路即可,话说拓扑排序求最长路真方便... 注意: 要明确拓扑的写法,要用栈写最优. 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define man 100010 4 inline i

2017 Multi-University Training Contest - Team 9 1005&amp;&amp;HDU 6165 FFF at Valentine【强联通缩点+拓扑排序】

FFF at Valentine Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1060    Accepted Submission(s): 506 Problem Description At Valentine's eve, Shylock and Lucar were enjoying their time as any oth