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;
    }
    

      

  • 相关阅读:
    LeetCode "Palindrome Partition II"
    LeetCode "Longest Substring Without Repeating Characters"
    LeetCode "Wildcard Matching"
    LeetCode "Best Time to Buy and Sell Stock II"
    LeetCodeEPI "Best Time to Buy and Sell Stock"
    LeetCode "Substring with Concatenation of All Words"
    LeetCode "Word Break II"
    LeetCode "Word Break"
    Some thoughts..
    LeetCode "Longest Valid Parentheses"
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/5914286.html
Copyright © 2011-2022 走看看