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

POJ 2186 Popular Cows(强连通分量+缩点)

2016-02-04 21:48 399 查看
题意: 给你一个有向图,现在问你图中有多少个顶点满足下面要求:任何其他的点都有路可以走到该顶点. 输出满足要求顶点的数目.

思路:首先我们把图的各个强连通分量算出来,对于分量A,如果A中的点a是那个图中所有点都可以到达的点,那么A中的其他所有点也都符合要求.

所以我们只需要把每个分量缩成一点,得到一个DAG有向无环图.然后看该DAG中的哪个点是所有其他点都可以到达的即可.那么该点代表的分量中的节点数就是所求答案.

如果DAG中出度为0的点仅有一个,那个出度为0的点代表的分量就是我们所找的分量.否则输出0.(这个结论需要自己仔细验证体会)

可不可能DAG中有两个点(分量)是满足要求的?(即分量中的所有点都是其他点可到达的)不可能,因为这两个分量如果互相可达,就会合并成一个分量.

会不会出现就算出度为0的点只有一个,但是DAG中的其他点到不了该出度为0的点,那么也应该输出0呢?如果DAG其他的点到不了出度为0的点,那么其他点必然还存在一个出度为0的点.矛盾.

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <set>
#include <ctime>
#include <cmath>
#include <cctype>
#include <stack>
using namespace std;
#define maxn 10000+100
#define LL long long
int cas=1,T;
vector<int>G[maxn];
int pre[maxn];
int lowlink[maxn];
int sccno[maxn];
int num[maxn];            //在i编号scc中有多少个点
int dfs_clock,scc_cnt;
int n,m;
stack<int>S;
void dfs(int u)
{
pre[u]=lowlink[u]=++dfs_clock;
S.push(u);
for (int i = 0;i<G[u].size();i++)
{
int v = G[u][i];
if (!pre[v])
{
dfs(v);
lowlink[u] = min(lowlink[u],lowlink[v]);
}
else if (!sccno[v])
{
lowlink[u] = min (lowlink[u],pre[v]);
}
}
if (lowlink[u] == pre[u])
{
scc_cnt++;
for (;;)
{
int x = S.top();S.pop();
sccno[x] = scc_cnt;
num[scc_cnt]++;
if (x==u)
break;
}
}
}

void find_scc(int n)
{
dfs_clock=scc_cnt=0;
memset(sccno,0,sizeof(sccno));
memset(pre,0,sizeof(pre));
for (int i = 1;i<=n;i++)
if (!pre[i])
dfs(i);
}
int in[maxn];
int out[maxn];
int main()
{
//freopen("in","r",stdin);
while (scanf("%d%d",&n,&m)==2)
{
for (int i = 0;i<=n;i++)
G[i].clear();
memset(out,0,sizeof(out));
memset(num,0,sizeof(num));
for (int i = 1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
}
find_scc(n);
for (int i = 1;i<=scc_cnt;i++)
{
out[i]=true;
}
for (int u = 1;u<=n;u++)
for (int i =0;i<G[u].size();i++)
{
int v = G[u][i];
if (sccno[u] != sccno[v])
out[sccno[u]]=false;
}
int b=0;
int pos;
for (int i = 1;i<=scc_cnt;i++)
{
if (out[i])
b++,pos=i;
}
if (b==1)
printf("%d\n",num[pos]);
else
printf("0\n");
}
return 0;
}


Description

Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows, you are given up to M (1 <= M <= 50,000) ordered pairs of the form (A, B) that tell you that cow A thinks that cow B is popular. Since popularity is transitive,
if A thinks B is popular and B thinks C is popular, then A will also think that C is

popular, even if this is not explicitly specified by an ordered pair in the input. Your task is to compute the number of cows that are considered popular by every other cow.

Input

* Line 1: Two space-separated integers, N and M

* Lines 2..1+M: Two space-separated numbers A and B, meaning that A thinks B is popular.

Output

* Line 1: A single integer that is the number of cows who are considered popular by every other cow.

Sample Input

3 3
1 2
2 1
2 3


Sample Output

1


Hint

Cow 3 is the only cow of high popularity.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: