ACM: 图论题 poj 2186 强连通分量

来源:互联网 发布:win7如何安装linux系统 编辑:程序博客网 时间:2024/05/19 10:40
PopularCows

 

Description

Every cow's dream is to becomethe most popular cow in the herd. In a herd of N (1<= N <= 10,000) cows, you are givenup to M (1 <= M <= 50,000) orderedpairs of the form (A, B) that tell you that cow A thinks that cow Bis popular. Since popularity is transitive, if A thinks B ispopular and B thinks C is popular, then A will also think that Cis
popular, even if this is not explicitly specified by an orderedpair in the input. Your task is to compute the number of cows thatare considered popular by every other cow.

Input

* Line 1: Two space-separatedintegers, N and M

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

Output

* Line 1: A single integer thatis the number of cows who are considered popular by every othercow.

Sample Input

3 3
1 2
2 1
2 3

Sample Output

1

Hint

Cow 3 is the only cow of highpopularity.
题意: 给出每头牛u觉得牛v是受欢迎的, 欢迎是具有传递性的,u->v, v->e ==>u->e
      现在计算出最受欢迎的牛的个数,大家都认为才是最受欢迎, 否则为0
 
解题思路:
     1. 一开始觉得题目很别扭, 最受欢迎并且是大家都认为的. 可仔细想想, 把全部支持
         popularity牛看成一个集合,集合内肯定有一条边指向popularity牛, 那么就可以发
        现, 全部支持popularity的牛是一个强连通分量, 而popularity牛也是一个强连通分
         量.
      2.一个有向图中, 如果存在至少两个孤立强连通分量, 那么题目无解.(全部认为才有解).
         否则,每个强连通分量必定是彼此有一条边相连, 那么肯定会出现一个强连通分量, 它
        是最受欢迎的, 并且集合元素个数就是解.(孤立指: 无法连通)
     3. 题目分析完毕, 剩下是求强连通分量, tarjan算法即可.
 
代码:
#include<cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define MAX 50005
#define MAXSIZE 10005
struct node
{
 int v;
 int next;
}edges[MAX];
int n, m;
int first[MAX], num;
int stack[MAXSIZE], top, bcc[MAXSIZE], count;
int dfn[MAXSIZE], low[MAXSIZE];
bool vis[MAXSIZE], flag[MAXSIZE];
int temp[MAXSIZE];
inline int min(int a, intb)
{
 return a < b ? a : b;
}
inline void add(int u, intv)
{
 edges[num].v =v;
 edges[num].next = first[u];
 first[u] = num++;
}
void readGraph()
{
 num = top = count = 0;
 memset(first, -1, sizeof(first));
 memset(vis, false, sizeof(vis));
 memset(bcc, 0, sizeof(bcc));
 memset(dfn, 0, sizeof(dfn));
 memset(low, 0, sizeof(low));
 memset(temp, 0, sizeof(temp));
 memset(flag, true, sizeof(flag));
 int u, v;
 for(int i = 0; i < m; ++i)
 {
  scanf("%d %d",&u, &v);
  add(u, v);
 }
}
void tarjan(int u, intdeep)
{
 dfn[u] = low[u] = deep+1;
 vis[u] = true;
 stack[top++] = u;
 for(int e = first[u]; e != -1; e =edges[e].next)
 {
  int v = edges[e].v;
  if( !low[v] )
  {
   tarjan(v,deep+1);
   low[u] =min(low[u], low[v]);
  }
  else if( vis[v] )
   low[u] =min(low[u], dfn[v]);
 }
 if(dfn[u] ==low[u])
 {
  count++;
  int v;
  do
  {
   v =stack[--top];
   vis[v] =false;
   bcc[v] =count;
  }while( v != u);
 }
}
int solve()
{
 int i;
 int result = 0;
 int number = 0;
 for(i = 1; i <= n; ++i)
 {
  if( !low[i] )
   tarjan(i, 1);//i, deep
 }
 for(i = 1; i<= n; ++i)
 {
  temp[ bcc[i] ]++;
  for(int e = first[i]; e != -1;e = edges[e].next)
  {
   if( bcc[i] !=bcc[ edges[e].v ] )
    flag[bcc[i] ] = false;
  }
 }
 for(i = 1; i<= count; ++i)
 {
  if( flag[i] )
  {
   number++;
   result =temp[i];
  }
 }
 if(number == 1) return result;
 else return 0;
}
int main()
{
// freopen("input.txt", "r", stdin);
 while(scanf("%d %d", &n,&m) != EOF)
 {
  readGraph();
  int result = solve();
  printf("%d\n", result);
 }
 return 0;
}
0 0
原创粉丝点击