• poj 2186 Popular Cows


    /*
    题意:
    给一个有向图,问有多少个点,是其他点都可以到达的
    其他点都可以到达该点,那么将图转置,就变为该点可以到达其他所有的点
    要找这样的点方法有很多,仿照Floyd的DP方法就是最容易写,但是点太多达到10000,会超时
    这里用SCC来做
    将转置后的图进行缩点,得到一个DAG,这个DAG每个大点内的小点(即原来的点)都是相互可达,关键是看这些大点能不能
    去到其他大点,如果一个大点能去到其他所有的大点,那么里面的小点也可以
    所以就是要找,有多少个大点,可以去到所有其他的大点,可知这样的大点,最多1个!!,而且是入度为0的点
    (这个不难理解,可以思考一下)
    找到了这个大点,那么里面包含的小点就都是可以的,所以扫描所有的小点,看是不是属于这个大点的,就可以计数了
    */
    
    #include <cstdio>
    #include <cstring>
    #define N 10010
    #define M 50010
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    
    int n,tot;
    int dcnt,bcnt,top;
    int stack[N];
    bool ins[N];
    int dfn[N],low[N],belong[N];
    int inde[N],outde[N];
    int head[N];
    struct edge
    {
        int u,v,next;
    }e[M];
    
    void add(int u ,int v , int k)
    {
        e[k].u = u;  e[k].v = v;
        e[k].next = head[u];  head[u] = k;
    }
    
    void tarjan(int u)
    {
        stack[++top] = u;
        ins[u] = true;
        dfn[u] = low[u] = ++dcnt;
        for(int k=head[u]; k!=-1; k=e[k].next)
        {
            int v = e[k].v;
            if(!dfn[v])
            {
                tarjan(v);
                low[u] = min(low[u] , low[v]);
            }
            else if(ins[v])
                low[u] = min(low[u] , dfn[v]);
        }
        if(dfn[u] == low[u])
        {
            ++bcnt;
            while(1)
            {
                int x = stack[top--];
                ins[x] = false;
                belong[x] = bcnt;
                if(x == u) break;
            }
        }
    }
    
    int main()
    {
        scanf("%d%d",&n,&tot);
        memset(head,-1,sizeof(head));
        for(int i=0; i<tot; i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add(v,u,i);
        }
    
        memset(dfn,0,sizeof(dfn));
        memset(ins,false,sizeof(ins));
        dcnt = bcnt = top = 0;
        for(int i=1; i<=n; i++)
            if(!dfn[i])
                tarjan(i);
    
        memset(inde,0,sizeof(inde));
        memset(outde,0,sizeof(outde));
        for(int i = 0; i<tot; i++)
        {
            int u = belong[e[i].u];
            int v = belong[e[i].v];
            if(u != v)
            {
                ++outde[u];
                ++inde[v];
            }
        }
        int c = 0 , x = 1;
        for(int i=1; i<=bcnt; i++)
            if(!inde[i])
            {
                c++;
                x = i;
            }
        if(c != 1) printf("0\n"); //大点只可以有1个
        else
        {
            int c = 0;
            for(int i=1; i<=n; i++)
                if(belong[i] == x)
                    c++;
            printf("%d\n",c);
        }
        return 0;
    }
  • 相关阅读:
    [POJ 1050]To the Max
    P1678 烦恼的高考志愿
    P1873 砍树
    P1102 A-B 数对
    P6771 [USACO05MAR]Space Elevator 太空电梯
    P2347 砝码称重
    P1832 A+B Problem(再升级)
    P1679 神奇的四次方数
    P1877 [HAOI2012]音量调节
    P1049 装箱问题
  • 原文地址:https://www.cnblogs.com/scau20110726/p/3070896.html
Copyright © 2020-2023  润新知