• POJ


    题意:判断一个有向图中的任意两点u、v,是否可以由其中一个点到达另一个点。

    分析:这个问题转化以后就是:将该图强连通缩点后再判断其是否是单向连通的。缩点用Tarjan处理强连通分量。

    有一个定理是这样的:一个有向图是单项连通的当且仅当其拓扑排序唯一。那么将这个子问题再转化为其缩点之后的图拓扑排序是否唯一。

    如果一个有向图拓扑排序唯一,那么在根据入度求拓扑排序的过程中,不会有超过一个点在同一时刻同时为0。

    #include<stack>
    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    #include<cstring>
    #include<queue>
    using namespace std;
    typedef long long LL;
    const int MAXN = 1e3+10;
    struct Edge{
        int to,next;
    }edges[MAXN<<3],E[MAXN<<3];
    int ID,H[MAXN];
    int dfn[MAXN],low[MAXN],sccno[MAXN],head[MAXN],tot,dfs_clock,scc_cnt,in[MAXN],sccnum[MAXN];
    stack<int> S;
    
    void init()
    {
        ID=dfs_clock=tot=scc_cnt=0;
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(in,0,sizeof(in));
        memset(sccno,0,sizeof(sccno));
        memset(head,-1,sizeof(head));
        memset(H,-1,sizeof(H));
    }
    
    void Tarjan(int u)
    {
        int v;
        dfn[u]=low[u]=++dfs_clock;
        S.push(u);
        for(int i=head[u];~i;i=edges[i].next){
            v = edges[i].to;
            if(!dfn[v]){
                Tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(!sccno[v]){
                low[u]=min(low[u],dfn[v]);
            }
        }
        if(dfn[u]==low[u]){
            ++scc_cnt;
            while(true){
                int x = S.top();S.pop();
                sccno[x] = scc_cnt;
                if(x==u) break;
            }
        }
    }
    
    void AddEdge(int u,int v)
    {
        edges[tot]=(Edge){v,head[u]};
        head[u]=tot++;
    }
    void new_AddEdge(int u,int v){
        E[ID]= (Edge){v,H[u]};
        H[u]=ID++;
    }
    
    bool Topo()
    {
        queue<int> Q;
        for(int u=1;u<=scc_cnt;++u){
            if(!in[u]) Q.push(u);
        }
        if(Q.size()>1) return false;
        while(!Q.empty()){
            int x = Q.front();Q.pop();
            for(int i=H[x];~i;i=E[i].next){
                int v =E[i].to;
                in[v]--;
                if(!in[v]) Q.push(v);
            }
            if(Q.size()>1) return false;
        }
        return true; 
    }
    
    int main()
    {
        #ifndef ONLINE_JUDGE
             freopen("in.txt","r",stdin);
             freopen("out.txt","w",stdout);
        #endif
        int T,N,M,u,v;
        scanf("%d",&T); 
        while(T--){
            scanf("%d%d",&N,&M);
            init();
            for(int i=1;i<=M;++i){
                scanf("%d%d",&u,&v);
                AddEdge(u,v);
            }
            for(int i=1;i<=N;++i){
                if(!dfn[i])Tarjan(i);
            }
            for(int u=1;u<=N;++u){
                for(int i=head[u];~i;i=edges[i].next){
                    int v=edges[i].to;
                    if(sccno[u]!=sccno[v]){
                        new_AddEdge(sccno[u],sccno[v]);
                        in[sccno[v]]++;
                    }
                }            
            }
            if(Topo()||scc_cnt==1) printf("Yes
    ");
            else printf("No
    ");
        }
        return 0;
    }
    为了更好的明天
  • 相关阅读:
    知识搜索
    使用 getopt() 进行命令行处理
    【新提醒】夏新大v安卓4.1尝鲜最新更新版本发布(包含进步版)1124更新 大V综合交流区 360论坛
    搜狗知立方高调亮相 开启知识计算新时代
    socat: Linux / UNIX TCP Port Forwarder
    Crontab 每两周执行一次
    python 命令行解析 optionparser
    crontab jojo's blog--快乐忧伤都与你同在 BlogJava
    搜索引擎开始「实体搜索」新领域竞争,Google、百度分别发力实体搜索产品
    netcat(nc)的替代产品 Socat
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9395321.html
Copyright © 2020-2023  润新知