您的位置:首页 > 运维架构

[POJ2186]Popular Cows

2014-04-02 08:22 387 查看
大意就是给定一个有向图,求有多少个顶点是由任何顶点出发都可达的。

顶点数<= 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;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  tarjan 图论