zoukankan      html  css  js  c++  java
  • 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 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条单向边。构成一个图,问你是否可以保证任选2个点u、v,这两个点之间是连通的?(能从x到达y,或者能从y到达x既可,不一定是x与y是互通
    的) 保证则输出:Yes 否则:No 【强连通缩点, 到最后我们只要进行一次拓扑排序,看看是否存在一条一次可以走完的路径既可】
    强连通分量算法将图化简缩点后,进行拓扑排序。
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <vector>
    #include <stack>
    #include <algorithm>
    #define N 1002
    
    using namespace std;
    
    struct node
    {
        int e, val;
    }item;
    vector<node>g[N];
    stack<int>st;
    
    int dfn[N], low[N];
    int id[N]; //标记i节点属于哪个连通分量
    int mat2[N][N];
    int n2;
    int counter, n, scnt;
    
    void Tarjan(int e)
    {
        int t, i;
        int mm=low[e]=dfn[e]=counter++;
        st.push(e);//入栈
        for(i=0; i<g[e].size(); i++){
            t=g[e][i].e;
            if(dfn[t]==-1)
                Tarjan(t);
            if(low[t]<mm)
                mm=low[t];
        }
        if(mm<low[e]){//有回边
            low[e]=mm; return;
        }
        do{
            id[t=st.top()]=scnt; low[t]=n;
            st.pop();
        }while(t!=e);
        scnt++;
    }
    
    void Search(int n)
    {
        int i;
        memset(dfn, -1, sizeof(dfn));
        counter=0; scnt=0;
        for(i=0; i<n; i++)
            if(dfn[i]==-1)
                Tarjan(i);
    }
    
    void base_vertex()
    {
        int i, j, t;
        Search(n); //调用求强连通分量
        n2=scnt;
        memset(mat2,0,sizeof(mat2));
        for(i=0; i<n; i++){
            for(j=0; j<g[i].size(); j++){
                t=g[i][j].e; mat2[id[i]][id[t]]=1;
            }
        }
    }
    
    int topo_sort(int n, int mat[][N], int *topo)
    {//拓扑排序的n是强连通分量的个数
        int d[N], i, j, k;
        for(i=0; i<n; i++){
            d[i]=0;
            for(j=0; j<n; j++)
                d[i]=d[i]+mat[j][i];//入度数
        }
        for(k=0; k<n; k++){
            for(i=0; d[i]&&i<n; i++);
            if(i==n) return 0;
            d[i]=-1;
            for(j=0; j<n; j++)
                d[j]-=mat[i][j];
            topo[k]=i;
        }
        return 1;
    }
    int main()
    {
        int tg; scanf("%d", &tg);
        int m, u, v;
        int i, j;
        int topo[N];
        while(tg--)
        {
            scanf("%d %d", &n, &m);
            for(i=0; i<=n; i++)
                g[i].clear();
            for(i=0; i<m; i++){
                scanf("%d %d", &u, &v);
                item.e=v-1; item.val=1;
                g[u-1].push_back(item);
            }//建立单向图
            base_vertex();
            topo_sort(n2, mat2, topo);
            int flag=1;
            for(i=0; i<n2-1; i++){
                if(!mat2[topo[i]][topo[i+1]] ){
                    flag=0; break;
                }
            }
            if(flag) printf("Yes
    ");
            else printf("No
    ");
        }
        return 0;
    }
    
    /*
        下面的数据会访问冲突崩溃掉 但poj可以Accepted 不懂~~~
    1
    8 11
    1 2
    2 3
    2 5
    2 6
    3 5
    4 3
    5 2
    5 4
    6 7
    6 8
    7 6
    
    */
    
    
    
  • 相关阅读:
    GZOI 2017配对统计 树状数组
    关于线段树的一些问题
    BZOJ 压力 tarjan 点双联通分量+树上差分+圆方树
    洛谷4552 差分
    洛谷5026 Lycanthropy 差分套差分
    【锁】MySQL和Oracle行锁比较
    oracle体系结构
    【加密】RSA验签及加密
    【Shiro】SpringBoot集成Shiro
    【Eureka】实现原理
  • 原文地址:https://www.cnblogs.com/yspworld/p/4769182.html
Copyright © 2011-2022 走看看