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

【POJ 2186 Popular Cows】+ 强连通

2017-03-09 20:03 357 查看
Popular Cows

Time Limit: 2000MS Memory Limit: 65536K

Total Submissions: 32649 Accepted: 13307

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.

Source

题意: 如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。问有多少头牛被所有的牛认为是受欢迎的

所谓强连通图 : 对于一个有向图顶点的子集S,在S里任取两个顶点u,v的都可以找到 一条u到v的路径

dfs 遍历所有顶点~再rdfs后序遍历顺序的顶点列表,并拓扑排序,此时强连图被当作一个节点来对待~且强连通图内拓扑序相同

对于本题 : 统计拓扑序为最后一个的节点个数,并记录该节点(对于强连通内的节点,记录热任意一个都是一样的),判断是否所以节点都可到达~

AC代码:

#include<cstdio>
#include<map>
#include<vector>
using namespace std;
const int K = 1e5 + 10;
vector <int> v[K]; // 建图
vector <int> v1[K]; // 图反向边
vector <int> v2; // 后续遍历顺序的顶点列表
map <int,int> m; // 标记访问
int o[K],N,M; // 所属强连通分量的拓扑序
void dfs(int p){
m[p]++;
for(int i = 0; i < v[p].size(); i++)
if(!m[v[p][i]]) dfs(v[p][i]);
v2.push_back(p);
}
void rdfs(int p,int nl){ // 反向建图遍历
m[p]++,o[p] = nl;
for(int i = 0; i < v1[p].size(); i++)
if(!m[v1[p][i]]) rdfs(v1[p][i],nl);
}
int sc(){
m.clear(),v2.clear();
for(int i = 1; i <= N; i++)
if(!m[i]) dfs(i);
m.clear();
int pl = 0;
for(int i = v2.size() - 1; i >= 0; i--)
if(!m[v2[i]]) rdfs(v2[i],++pl);
return pl; // 强连通分量 S 算做一个节点,共有多少个节点
}
int main()
{
int a,b;
while(scanf("%d %d",&N,&M) !=EOF){
for(int i = 1; i <= M; i++)
scanf("%d %d",&a,&b),v[a].push_back(b), v1[b].push_back(a);
int nl = sc(),num = 0,u = 0;
for(int i = 1; i <= N; i++)
if(o[i] == nl) num++,u = i;
m.clear();rdfs(u,1);
for(int i = 1;  i <= N; i++)
if(!m[i]){ // 从该点不可达
num = 0;break;
}
printf("%d\n",num);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj