【poj2186】 Popular Cows

来源:互联网 发布:儿童节礼物 知乎 编辑:程序博客网 时间:2024/05/17 12:05

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\n");        else {            ans=0;            for (int i=1;i<=tot;i++) if (!f[i]) ans+=cnts[i];            printf("%d\n",ans);        }    }    return 0;}
0 0