• poj2186-Popular Cows【Tarjan】+(染色+缩点)(经典)


    <题目链接>

    题目大意:

    有N(N<=10000)头牛,每头牛都想成为most poluler的牛,给出M(M<=50000)个关系,如(1,2)代表1欢迎2,关系可以传递,但是不可以相互,即1欢迎2不代表2欢迎1,但是如果2也欢迎3那么1也欢迎3.
    给出N,M和M个欢迎关系,求被所有牛都欢迎的牛的数量。

    解题分析:

    仔细思考后发现,其实题目就是问你,在给出的这个有向图中的所有连通分量中,是否存在唯一出度为0的连通分量,如果存在,则输出这个连通分量中所有点的个数。

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <map>
    using namespace std;
    
    #define pb push_back
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define clr(a,b) memset(a,b,sizeof(a))
    const int N = 1e4+5 , M = 5e4+5;
    
    struct Edge{ int from,to,nxt; }e[M<<1];
    int n,m,cnt,tot,scc,top;
    int stk[N],instk[N],head[N],dfn[N],low[N],bel[N],out[N];
    
    inline void init(){
        cnt=tot=scc=top=0;
        clr(head,-1);clr(dfn,0);clr(low,0);clr(bel,0);
        clr(out,0);clr(instk,0);
    }
    inline void add(int u,int v){
        e[++cnt]=(Edge){u,v,head[u]};head[u]=cnt;
    }
    void Tarjan(int u){
        dfn[u]=low[u]=++tot;
        instk[u]=1,stk[++top]=u;
        for(int i=head[u];~i;i=e[i].nxt){
            int v=e[i].to;
            if(!dfn[v]){
                Tarjan(v);
                low[u]=min(low[u],low[v]);
            }else if(instk[v])low[u]=min(low[u],dfn[v]);
        }
        if(dfn[u]==low[u]){
            ++scc;
            while(true){
                int v=stk[top--];
                instk[v]=0;
                bel[v]=scc;
                if(v==u)break;
            }    
        }
    }
    inline void Solve(){
        rep(i,1,cnt){
            int u=e[i].from,v=e[i].to;
            if(bel[u]!=bel[v]){
                out[bel[u]]++;        //统计每个强连通分量的出度
            }
        }
        int num=0,loc=-1;
        rep(i,1,scc){
            if(!out[i])num++,loc=i;
        }
        if(num==1){
            int ans=0;
            rep(i,1,n) if(bel[i]==loc){
                ans++;
            }
            printf("%d
    ",ans);
        }else puts("0");
    }
    int main(){
        while(~scanf("%d%d",&n,&m)){
            init();
            rep(i,1,m){
                int u,v;scanf("%d%d",&u,&v);
                add(u,v);
            }
            rep(i,1,n) if(!dfn[i]){
                Tarjan(i);
            }
            Solve();
        }
    }

    2018-08-16

  • 相关阅读:
    web服务器的设置
    java数字图像处理常用算法(转)
    Delphi 7.0常用函数速查手册
    直方图均衡子函数
    Delphi6/7 中XML 文档的应用
    区域增长算法
    Java中的异常栈轨迹和异常链
    Arrays类和Collections的运用
    Java中内部类对象的创建以及hook机制
    Java中的容器
  • 原文地址:https://www.cnblogs.com/00isok/p/9489503.html
Copyright © 2020-2023  润新知