poj 2186 Popular Cows :求能被有多少点是能被所有点到达的点 tarjan O(E)

  1 /**
  2 problem: http://poj.org/problem?id=2186
  3 
  4 当出度为0的点(可能是缩点后的点)只有一个时就存在被所有牛崇拜的牛
  5 因为如果存在有两个及以上出度为0的点的话,他们不会互相崇拜所以不存在被所有牛崇拜的牛
  6 牛的个数即该出度为0点(由环缩点而来)有多少牛
  7 **/
  8 #include<stdio.h>
  9 #include<stack>
 10 #include<algorithm>
 11 using namespace std;
 12 
 13 class Graphics{
 14     const static int MAXN = 10005;
 15     const static int MAXM = 50005;
 16 private:
 17     struct Edge{
 18         int to, next;
 19     }edge[MAXM];
 20     struct Point{
 21         int dfn, low, color;
 22     }point[MAXN];
 23     int sign, dfnNum, colorNum, sumOfPoint, first[MAXN], count[MAXN];
 24     bool vis[MAXN];
 25     stack<int> stk;
 26     void tarjan(int u){
 27         point[u].dfn = ++dfnNum;
 28         point[u].low = dfnNum;
 29         vis[u] = true;
 30         stk.push(u);
 31         for(int i = first[u]; i != -1; i = edge[i].next){
 32             int to = edge[i].to;
 33             if(!point[to].dfn){
 34                 tarjan(to);
 35                 point[u].low = min(point[to].low, point[u].low);
 36             }else if(vis[to]){
 37                 point[u].low = min(point[to].dfn, point[u].low);
 38             }
 39         }
 40         if(point[u].dfn == point[u].low){
 41             vis[u] = false;
 42             point[u].color = ++colorNum;
 43             count[colorNum] ++;
 44             while(stk.top() != u){
 45                 vis[stk.top()] = false;
 46                 point[stk.top()].color = colorNum;
 47                 count[colorNum] ++;
 48                 stk.pop();
 49             }
 50             stk.pop();
 51         }
 52     }
 53 public:
 54     void clear(int n){
 55         sign = dfnNum = colorNum = 0;
 56         for(int i = 1; i <= n; i ++){
 57             first[i] = -1;
 58             vis[i] = 0;
 59             count[i] = 0;
 60         }
 61         sumOfPoint = n;
 62         while(!stk.empty()) stk.pop();
 63     }
 64     void addEdgeOneWay(int u, int v){
 65         edge[sign].to = v;
 66         edge[sign].next = first[u];
 67         first[u] = sign ++;
 68     }
 69     void addEdgeTwoWay(int u, int v){
 70         addEdgeOneWay(u, v);
 71         addEdgeOneWay(v, u);
 72     }
 73     void tarjanAllPoint(){
 74         for(int i = 1; i <= sumOfPoint; i ++){
 75             if(!point[i].dfn)
 76                 tarjan(i);
 77         }
 78     }
 79     int getAns(){
 80         int ans = 0, ans2 = 0;
 81         int *outdegree = new int[sumOfPoint+1];
 82         for(int i = 1; i <= sumOfPoint; i ++){
 83             outdegree[i] = 0;
 84         }
 85         tarjanAllPoint();
 86         for(int i = 1; i <= sumOfPoint; i ++){
 87             for(int j = first[i]; j != -1; j = edge[j].next){
 88                 int to = edge[j].to;
 89                 if(point[to].color != point[i].color){
 90                     outdegree[point[i].color] ++;
 91                 }
 92             }
 93         }
 94         for(int i = 1; i <= colorNum; i ++){
 95             if(!outdegree[i]){
 96                 ans ++;
 97                 ans2 = count[i];
 98             }
 99         }
100         delete []outdegree;
101         if(ans == 1){
102             return ans2;
103         }else{
104             return 0;
105         }
106     }
107 }graph;
108 
109 int main(){
110     int n, m;
111     scanf("%d%d", &n, &m);
112     graph.clear(n);
113     while(m --){
114         int a, b;
115         scanf("%d%d", &a, &b);
116         graph.addEdgeOneWay(a, b);
117     }
118     printf("%d\n", graph.getAns());
119     return 0;
120 }

 

posted @ 2019-03-14 23:03  DarkScoCu  阅读(133)  评论(0编辑  收藏  举报