zoukankan      html  css  js  c++  java
  • 【poj2186】 Popular Cows

    http://poj.org/problem?id=2186 (题目链接)

    题意

      给出一个n个点m条边的有向图,求其中没有出度强连通分量所包含的点有几个

    Solution 

      其实这道题的题解已经在“题意”中给出了= =,先Tarjan跑出强连通分量,之后模拟给缩点后的图连边(其实并不用真的连边),来统计缩点后每个节点的出度。输出出度为0的强连通分量所包含的点即可,若有多个强连通分量出度为0,输出0(不要问我为什么,有时候事情就是这么不讲道理)。

    代码

    // poj2186
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<set>
    #define MOD 1000000007
    #define inf 2147483640
    #define LL long long
    #define free(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout);
    using namespace std;
    inline LL getint() {
        LL x=0,f=1;char ch=getchar();
        while (ch>'9' || ch<'0') {if (ch=='-') f=-1;ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    
    const int maxn=50010;
    struct edge {int to,next;}e[maxn<<2];
    int f[maxn],dfn[maxn],low[maxn],head[maxn],s[maxn],pos[maxn],cnts[maxn];
    int ind,cnt,n,m,top,tot;
    
    void insert(int u,int v) {
        e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;
    }
    void Tarjan(int u) {
        dfn[u]=low[u]=++ind;
        s[++top]=u;
        f[u]=1;
        for (int i=head[u];i;i=e[i].next) {
            if (!dfn[e[i].to]) {
                Tarjan(e[i].to);
                low[u]=min(low[u],low[e[i].to]);
            }
            else if (f[e[i].to]) low[u]=min(low[u],dfn[e[i].to]);
        }
        if (dfn[u]==low[u]) {
            tot++;int j;
            do {
                j=s[top--];
                pos[j]=tot;
                cnts[tot]++;
                f[j]=0;
            }while (j!=u);
        }
    }
    int main() {
        while (scanf("%d%d",&n,&m)!=EOF) {
            top=0;cnt=0;ind=0;tot=0;
            for (int i=1;i<=n;i++) dfn[i]=low[i]=head[i]=cnts[i]=pos[i]=0;
            for (int i=1;i<=m;i++) {
                int x,y;
                scanf("%d%d",&x,&y);
                insert(x,y);
            }
            for (int i=1;i<=n;i++) if (!dfn[i]) Tarjan(i);
            cnt=0;for (int i=1;i<=n;i++) f[i]=0;
            for (int i=1;i<=n;i++)
                for (int j=head[i];j;j=e[j].next)
                    if (pos[i]!=pos[e[j].to]) f[pos[i]]++;
            int ans=0;
            for (int i=1;i<=tot;i++) if (!f[i]) ans++;
            if (ans>1) printf("0
    ");
            else {
                ans=0;
                for (int i=1;i<=tot;i++) if (!f[i]) ans+=cnts[i];
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    成功后的迷失
    让主参与的人生
    生命的见证
    谁偷走了我的安全感
    简单理解分页原理
    WebApp开发入门
    程序员必需知道的搜索引擎的搜索技巧
    提高网页打开速度技巧
    十分钟了解HTTP协议
    简单实现页面临摹设计图功能
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/5914286.html
Copyright © 2011-2022 走看看