[POJ2186]Popular Cows

来源:互联网 发布:mac只装win10单系统 编辑:程序博客网 时间:2024/05/17 13:42
大意就是给定一个有向图,求有多少个顶点是由任何顶点出发都可达的。
顶点数<= 10,000,边数 <= 50,000

定理 有向无环图中唯一出度为0的点,一定可以由任何点出发均可达

由于无环,所以从任何点出发往前走,必然终止于一个出度为0的点

tarjan缩点后找是否有唯一出度为0的点存在

#include <iostream>#include<cstdio>#include<vector>#include<stack>#include<cstring>using namespace std;vector<int> p[50010];stack<int> s;int color[50010],out[50010],dfn[50010],low[50010],ind,tm,n,m;bool flag[50010],vis[50010];void tarjan(int now){    vis[now]=true;    dfn[now]=low[now]=++ind;    s.push(now);    flag[now]=true;    for (int i=0;i<(int)p[now].size();i++)    {        int v=p[now][i];        if (!vis[v])        {            tarjan(v);            low[now]=min(low[now],low[v]);        }        else if (flag[v]) low[now]=min(low[now],dfn[v]);    }    if (dfn[now]==low[now])    {        int v;        do        {            v=s.top();            s.pop();            flag[v]=false;            color[v]=tm;        } while(now!=v);        tm++;    }}int main(){    freopen("in.in","r",stdin);    scanf("%d%d",&n,&m);    for (int i=1;i<=m;i++)    {        int a,b;        scanf("%d%d",&a,&b);        p[a].push_back(b);    }    memset(vis,false,sizeof(vis));    memset(flag,false,sizeof(flag));    memset(out,0,sizeof(out));    ind=0;    tm=1;    for (int i=1;i<=n;i++)    {        if (!vis[i]) tarjan(i);    }    for (int i=1;i<=n;i++)    for (int j=0;j<(int)p[i].size();j++)    {        int x=p[i][j];        if (color[i]!=color[x]) out[color[i]]++;    }    int cans=0;    tm--;    for (int i=1;i<=tm;i++)    {        if (out[i]==0)        {            if (cans!=0) {cout<<0<<endl;return 0;}            else cans=i;        }    }    int ans=0;    for (int i=1;i<=n;i++)    if (color[i]==cans) ans++;    cout<<ans<<endl;    return 0;}


0 0
原创粉丝点击