zoukankan      html  css  js  c++  java
  • 迷宫城堡

    连通图 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

    Submit Status

    Description

    为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是 单向的,就是说若称某通道连通了A房间和B房间,只说明可以通过这个通道由A房间到达B房间,但并不说明通过它可以由B房间到达A房间。Gardon需要 请你写个程序确认一下是否任意两个房间都是相互连通的,即:对于任意的i和j,至少存在一条路径可以从房间i到房间j,也存在一条路径可以从房间j到房间 i。
     

    Input

    输入包含多组数据,输入的第一行有两个数:N和M,接下来的M行每行有两个数a和b,表示了一条通道可以从A房间来到B房间。文件最后以两个0结束。
     

    Output

    对于输入的每组数据,如果任意两个房间都是相互连接的,输出"Yes",否则输出"No"。
     

    Sample Input

    3 3
    1 2
    2 3
    3 1
     
    3 3
    1 2
    2 3
    3 2
     
    0 0
     

    Sample Output

    Yes
    No
    只要任意两点直接或间接连接,就是说这个图是一个强连通图;
    #include<iostream>
    #include<vector>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #include<stack>
    #include<cmath>
    
    using namespace std;
    
    #define N 10008
    
    int n, m, cnt, num, top, Time; // Time用来计量时间,top用来控制stackk数组的下标
    int dfn[N], low[N], stackk[N];  // dfn数组存到达下标的最小时间,low存下标可以走到的最小的点,stackk是自己建的栈,用来存深搜先后进入的点
    bool instack[N];  // 判断是否进栈
    
    vector<vector<int> > G;
    
    void init()   // 初始化
    {
        G.clear();
        G.resize(n+1);
        memset(dfn, 0, sizeof(dfn));
        memset(low, 0, sizeof(low));
        memset(stackk, 0, sizeof(stackk));
        memset(instack, false, sizeof(instack));
        cnt = num = top = Time = 0;
    }
    
    void Tarjan(int u)  // 从1点开始进栈,进栈一次Time更新
    {
        low[u] = dfn[u] = ++Time;
        stackk[top++] = u;
        instack[u] = true;  // 已经进栈就标记true
        int len = G[u].size(), v;  
    
        for(int i = 0; i < len; i++)
        {
            v = G[u][i];  // 与进栈的点所连接的点
    
            if(!dfn[v])  // 如果这个点还没有被访问过,就把这个点遍历,low随之更新,是原先值和连接的这个值的low的最小值,因为low是指下标所能到的最小的点
            {
                Tarjan(v);
                low[u] = min(low[u], low[v]);
            }
            else if(instack[v])  // 如果已经进栈,就直接判断low的取值就行了,
                low[u] = min(low[u], dfn[v]);
        }
        if(low[u] == dfn[u])  // 如果两个点的第一次到的时间值dfn和可以到的最小值dfn一样,说明不能再往下走了,这个连通图结束,开始出栈
        {
            do
            {
                num++;   // 出栈一个数num++,计量出栈总数
                v = stackk[--top];   // v用来存出栈的数,top--,
                instack[v] = false;  //  出栈置为false,虽然对本题没多大用
            }while(u != v);  // 当出栈是u时,出栈结束
            cnt++;   // 每 一次出栈,即每一个连通图,cnt++,
        }
    }
    
    void slove()
    {
        Tarjan(1);
    
        if(cnt == 1 && num == n)  // 如果cnt等于1,就是就一个连通图。而且连通图内的总数是n,即把每个数都连接在内了,那么久是一个连通图,满足题意
            puts("Yes");
        else
            puts("No");
    }
    
    int main()
    {
        while(scanf("%d%d", &n, &m), n+m)
        {
            int a, b;
            init();
    
            while(m--)
            {
                scanf("%d%d", &a, &b);
                G[a].push_back(b);  // 
            }
            slove();
        }
        return 0;
    }
    让未来到来 让过去过去
  • 相关阅读:
    Mysql推荐使用规范
    程序员应该经常浏览的技术网站
    百度,腾讯,阿里等互联网公司年终奖发多少
    JNI技术详解,让程序有飞一般的感觉
    日志:分布式系统的核心
    Spring Boot七:Spring boot集成MyBatis
    通俗理解TCP的三次握手
    JDBC添加数据
    JDBC概念
    今天是阳光明媚的一天
  • 原文地址:https://www.cnblogs.com/Tinamei/p/4705308.html
Copyright © 2011-2022 走看看