POJ 2762--Going from u to v or from v to u?【scc缩点新建图 && 推断是否是弱连通图】

Going from u to v or from v to u?

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 15755   Accepted: 4172

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

题意:是给出一些点,给出n个点和m条边,接着给出直接相连的边(注意是有向边),求解随意x,y两点间是否存在 x 可到达 y 或者y可

到达x,假设随意x和y都满足这种条件,就输出"Yes", 否则输出"No".。

注意。这里是 x 到达 y 或者 y 到达 x ,是或者不是并且 。!

假设是“并且”的话。非常明显的是推断整个图是否为一个强连通分量(如题HDU 1296 , 题目解析)。但这题并非这样。

本题应推断整个图是否为一个弱连通分量。

正确思路:先求解出该有向图的强连通分量。然后依据求解出来的强连通分量进行缩点又一次建图

问题转换为求解在新图中是否存在一条能走全然部的顶点的路径,这时能够对缩点后的新图进行拓扑排序,看拓扑排序能否够成功进行。

拓扑排序遵循条件

一:新图不能有多于1个的入度为0的点,这是保证每一个点都有边相连。

二:在拓扑排序遍历点u的过程中,若去掉与u相关的边后出现多于1个的入度为0的点,说明这些点仅仅能由u到达,而它们之间不存在可达路径。这时不满足弱连通,跳出。

#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
#define maxn 10000 + 100
#define maxm 100000 + 1000
using namespace std;
int n, m;
struct node {
	int u, v, next;
};
node edge[maxm];
int head[maxn], cnt;
int low[maxn], dfn[maxn];
int dfs_clock;
int Stack[maxn];
bool Instack[maxn];
int top;
int Belong[maxn] , scc_clock;
int in[maxn];
vector<int>Map[maxn];

void init(){
	cnt = 0;
	memset(head, -1, sizeof(head));
}

void addedge(int u, int v){
	edge[cnt] = {u, v, head[u]};
	head[u] = cnt++;
}

void getmap(){
    scanf("%d%d", &n, &m);
    while(m--){
        int a, b;
        scanf("%d%d", &a, &b);
        addedge(a, b);
    }
}

void tarjan(int u, int per){
    int v;
    low[u] = dfn[u] = ++dfs_clock;
    Stack[top++] = u;
    Instack[u] = true;
    for(int i = head[u]; i != -1; i = edge[i].next){
        v = edge[i].v;
        if(!dfn[v]){
            tarjan(v, u);
            low[u] = min(low[v], low[u]);
        }
        else if(Instack[v]){
            low[u] = min(low[u], dfn[v]);
        }
    }
    if(dfn[u] == low[u]){
        scc_clock++;
        do{
            v = Stack[--top];
            Instack[v] = false;
            Belong[v] = scc_clock;
        }while(u != v);
    }
}

void find(){
    memset(low, 0, sizeof(low));
    memset(dfn, 0, sizeof(dfn));
    memset(Instack, false, sizeof(Instack));
    memset(Belong, 0, sizeof(Belong));
    dfs_clock = scc_clock = top = 0;
    for(int i = 1; i <= n; ++i){
        if(!dfn[i])
            tarjan(i, i);
    }
}

void suodian(){
    for(int i = 1; i <= scc_clock; ++i){
        Map[i].clear();
        in[i] = 0;
    }
    for(int i = 0; i < cnt; ++i){
        int u = Belong[edge[i].u];
        int v = Belong[edge[i].v];
        if(u != v){
            Map[u].push_back(v);
            in[v]++;
        }
    }
}

void solve(){
    queue<int>q;
    int num = 0;
    for(int i = 1; i <= scc_clock; ++i){
        if(!in[i]){
            num++;
            q.push(i);
        }
        if(num > 1){
            printf("No\n");
            return ;
        }
    }
    while(!q.empty()){
        int u = q.front();
        q.pop();
        num = 0;
        for(int i = 0; i < Map[u].size(); ++i){
            int v = Map[u][i];
            in[v]--;
            if(!in[v]){
                num++;
                //有两个或两个以上的分支。不是弱连通
                if(num > 1){
                    printf("No\n");
                    return ;
                }
                q.push(v);
            }
        }
    }
    printf("Yes\n");
}

int main (){
    int T;
    scanf("%d", &T);
	while(T--){
        init();
        getmap();
        find();
        suodian();
        solve();
	}
	return 0;
}
时间: 2024-12-11 01:24:15

POJ 2762--Going from u to v or from v to u?【scc缩点新建图 &amp;&amp; 推断是否是弱连通图】的相关文章

POJ 3592--Instantaneous Transference【SCC缩点新建图 &amp;amp;&amp;amp; SPFA求最长路 &amp;amp;&amp;amp; 经典】

Instantaneous Transference Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 6177   Accepted: 1383 Description It was long ago when we played the game Red Alert. There is a magic function for the game objects which is called instantaneous

POJ 3592--Instantaneous Transference【SCC缩点新建图 &amp;&amp; SPFA求最长路 &amp;&amp; 经典】

Instantaneous Transference Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 6177   Accepted: 1383 Description It was long ago when we played the game Red Alert. There is a magic function for the game objects which is called instantaneous

POJ 2762--Going from u to v or from v to u?【scc缩点新建图 &amp;&amp; 判断是否是弱连通图】

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

POJ 2762 Going from u to v or from v to u?(强连通分量+拓扑排序)

职务地址:id=2762">POJ 2762 先缩小点.进而推断网络拓扑结构是否每个号码1(排序我是想不出来这点的. .. ).由于假如有一层为2的话,那么从此之后这两个岔路的点就不可能从一点到还有一点的. 代码例如以下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include

POJ 2762 Going from u to v or from v to u? (有向图求单连通性)

POJ 2762 Going from u to v or from v to u? 链接:http://poj.org/problem?id=2762 题意:为了让他们的儿子变得更勇敢些,Jiajia 和Wind 将他们带到一个大洞穴中.洞穴中有n 个房间,有一些单向的通道连接某些房间.每次,Wind 选择两个房间x 和y,要求他们的一个儿子从一个房间走到另一个房间,这个儿子可以从x 走到y,也可以从y 走到x.Wind 保证她布置的任务是可以完成的,但她确实不知道如何判断一个任务是否可以完成

POJ 2762 Going from u to v or from v to u? (判断弱连通)

http://poj.org/problem?id=2762 题意:给出有向图,判断任意两个点u和v,是否可以从u到v或者从v到u. 思路: 判断图是否是弱连通的. 首先来一遍强连通缩点,重新建立新图,接下来我们在新图中找入度为0的点,入度为0的点只能有1个,如果有多个那么这些个点肯定是不能相互到达的. 如果只有一个入度为0的点,走一遍dfs判断新图是否是单链,如果有分支,那么分支上的点肯定是不能相互到达的. 1 #include<iostream> 2 #include<algorit

[ tarjan + dfs ] poj 2762 Going from u to v or from v to u?

题目链接: http://poj.org/problem?id=2762 Going from u to v or from v to u? Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 14546   Accepted: 3837 Description In order to make their sons brave, Jiajia and Wind take them to a big cave. The cav

poj 2762 Going from u to v or from v to u? (判断是否是弱联通图)

题意:给定一个有向图有m条单向边,判断是否任意两点都可达(a能到b或者b能到a或者互相可达),即求 弱联通分量. 算法: 先缩点求强连通分量.然后重新建图,判断新图是否是一条单链,即不能分叉,如果分叉了就会存在不可达的情况. 怎么判断是否是单链呢? 就是每次入度为0的点都只有一个,即每次队列里只有一个点. (    o(╯□╰)o.....好像已经是第二次用pair记录原图的点对,然后存pair的vector忘记清空导致wa来wa去! ) #include<cstdio> #include&l

POJ 2762 Going from u to v or from v to u?(强联通,拓扑排序)

http://poj.org/problem?id=2762 Going from u to v or from v to u? Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 14573   Accepted: 3849 Description In order to make their sons brave, Jiajia and Wind take them to a big cave. The cave has