zoukankan      html  css  js  c++  java
  • 强连通图 Tarjan算法

    算法学习:https://blog.csdn.net/qq_16234613/article/details/77431043

                      http://www.cnblogs.com/chenchengxun/p/4718698.html

    题目链接:https://vjudge.net/contest/219056#problem/B

    为了训练小希的方向感,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<cstdio>
    #include<cstring>
    #include<stdio.h>
    #include<string.h>
    #include<cmath>
    #include<math.h>
    #include<algorithm>
    #include<set>
    #include<queue>
    #include<map>
    typedef long long ll;
    using namespace std;
    const ll mod=1e9+7;
    const int maxn=1e4+10;
    const int maxk=100+10;
    const int maxx=1e4+10;
    const ll maxe=1000+10;
    #define INF 0x3f3f3f3f3f3f
    int n,m,time=1,top,sum,block;
    int dfn[maxn],low[maxn];//dfn存储到该点的时间,low存储从该点能到达的最小序号
    int Stack[maxn];//自定义栈
    int instack[maxn];//instack判断是否入栈
    vector<int> G[maxn];
    void init()
    {
        memset(instack,0,sizeof(instack));
        memset(Stack,0,sizeof(Stack));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        for(int i=0;i<=n;i++)
            G[i].clear();
    }
    void solve(int u)
    {
        low[u]=dfn[u]=time++;//初始化为到该点的时间
        Stack[top++]=u;//把u入栈
        instack[u]=1;//标记已经入栈
        int v;
        for(int i=0;i<G[u].size();i++)
        {
            v=G[u][i];
            if(dfn[v]==0)//还没有访问过
            {
                solve(v);
                low[u]=min(low[u],low[v]);
            }
            else if(instack[v])//已经访问过,并且入栈
                low[u]=min(low[u],low[v]);
        }
        if(low[u]==dfn[u])//相等时代表有环,但是Tarjan算法一个点也被看作环
        {
    
            int m=Stack[--top];
            while(m!=u)
            {
                sum++;
                m=Stack[--top];
            }
            sum++;//加上本身
            block++;//这里是记录有多少个块,只能有一个块把所有的点都连成一个强连通图
        }
    
    }
    int main()
    {
        while(cin>>n>>m)
        {
            if(n==0&&m==0) break;
            sum=0;
            top=0;
            time=1;
            block=0;
            init();
            int u,v;
            for(int i=0;i<m;i++)
            {
                cin>>u>>v;
                G[u].push_back(v);
            }
            solve(1);
         //   cout<<sum<<" "<<block<<endl;
            if(block==1&&sum==n)
                cout<<"Yes"<<endl;
            else
                cout<<"No"<<endl;
        }
    }
    当初的梦想实现了吗,事到如今只好放弃吗~
  • 相关阅读:
    setTimeout,clearTimeout,setInterval,clearInteral详解
    关于JS读取DOM对象(标签)的自定义属性
    jquery.form.js官方插件介绍Form插件,支持Ajax,支持Ajax文件上传
    按回车键切换input鼠标光标
    电压跟随器的作用,以及其中两个电阻的作用?
    阅读RB521S30肖特基二极管的datasheet
    配置linux内核,解决lcd logo和十分钟息屏!
    配置linux,关闭LCD的console控制台输出。
    记录一次编译linux内核或者说编译dtbs的问题!!
    copy_from_user的详细用法!
  • 原文地址:https://www.cnblogs.com/caijiaming/p/9389108.html
Copyright © 2011-2022 走看看