1. 程式人生 > >數算實習 popular cow 強連通分量tarjan演算法

數算實習 popular cow 強連通分量tarjan演算法

popular cow 描述:有N頭牛。如果a喜歡b,b喜歡c,則a也會喜歡c。告訴你M個喜歡關係 ,比如(a,b)表示a喜歡b。問有多少頭牛是被所有牛都喜歡的。 N<= 10,000, M<= 50,000

樣例輸入 3 3 1 2 2 1 2 3

樣例輸出1

 #include <iostream>
 #include <algorithm>
 #include <string>
 #include <cstring>
 #include <stack>
 #include <vector>
 using namespace std;
 
 int n, m;
 int visited[10005] = { 0 };            //記錄是否被訪問
 int dfn[10005] = { 0 };                //遍歷
 int low[10005] = { 0 };                //可到達的最小結點
 int ntime = 0;                   
 stack<int> s; 
 vector<int> v[10005];                  //記錄邊
 int color[10005] = { 0 };              //用於染色
 int curcolor = 1;         
   
 void tarjan(int u)     
 {
  visited[u] = 1;
  s.push(u);
  dfn[u] = ++ntime;
  low[u] = ntime;
  for (int i = 0; i < v[u].size(); i++)
  {
   int q = v[u][i];
   if (visited[q] == 0)
   {
    tarjan(q);
    low[u] = min(low[u], low[q]);
   }
   else
    low[u] = min(low[u], dfn[q]);
  }
  if (dfn[u] == low[u])
  {
   int v = s.top();
   s.pop();
   while (v != u)      //染色
   {
    color[v] = curcolor;
    v = s.top();
    s.pop();
   }
   color[u] = curcolor;
   curcolor++;
  }
 }
 int sum[10005] = { 0 };
 
 int main()
 {
  cin >> n >> m;
  for (int i = 0; i < m; i++)
  {
   int a, b;
   cin >> a >> b;
   v[a].push_back(b);
  }
  for (int i = 1; i <= n; i++)
  {
   if (visited[i] == 0)
    tarjan(i);
  }
  for (int i = 1; i <= n; i++)
  {
   for (int j = 0; j < v[i].size(); j++)
   {
    int k = v[i][j];
    if (color[i] != color[k])
     sum[color[i]]++;
   }
  }
  int r = 0;
  int flag;
  for (int i = 1; i < curcolor; i++)
  {
   if (sum[i] == 0)
   {
    r++;
    flag = i;
   }
  }
  if (r >= 2)
   cout << "0" << endl;
  else
  {
   int result = 0;
   for (int i = 1; i <= n; i++)
   {
    if (color[i] == flag)
     result++;
   }
   cout << result << endl;
  }

  return 0;
 }