poj 2553 The Bottom of a Graph : tarjan O(n) 存环中的点

  1 /**
  2 problem: http://poj.org/problem?id=2553
  3 将所有出度为0环中的点排序输出即可。
  4 **/
  5 
  6 #include<stdio.h>
  7 #include<stack>
  8 #include<vector>
  9 #include<algorithm>
 10 using namespace std;
 11 
 12 class Graphics{
 13     const static int MAXN = 5005;
 14     const static int MAXM = MAXN * MAXN;
 15 private:
 16     struct Edge{
 17         int to, next;
 18     }edge[MAXM];
 19     struct Point{
 20         int dfn, low, color;
 21         Point(){dfn = low = color = 0;}
 22     }point[MAXN], emptyPoint;
 23     int first[MAXN], sign, colorNum, dfnNum, sumOfPoint;
 24     bool vis[MAXN];
 25     vector<int> ring[MAXN];
 26     stack<int> stk;
 27     void tarjan(int u){
 28         point[u].dfn = ++ dfnNum;
 29         point[u].low = dfnNum;
 30         vis[u] = true;
 31         stk.push(u);
 32         for(int i = first[u]; i != -1; i = edge[i].next){
 33             int to = edge[i].to;
 34             if(!point[to].dfn){
 35                 tarjan(to);
 36                 point[u].low = min(point[to].low, point[u].low);
 37             }else if(vis[to]){
 38                 point[u].low = min(point[to].dfn, point[u].low);
 39             }
 40         }
 41         if(point[u].low == point[u].dfn){
 42             vis[u] = false;
 43             point[u].color = ++colorNum;
 44             ring[colorNum].push_back(u);
 45             while(stk.top() != u){
 46                 vis[stk.top()] = false;
 47                 point[stk.top()].color = colorNum;
 48                 ring[colorNum].push_back(stk.top());
 49                 stk.pop();
 50             }
 51             stk.pop();
 52         }
 53     }
 54 public:
 55     void clear(int n){
 56         sign = colorNum = dfnNum = 0;
 57         sumOfPoint = n;
 58         for(int i = 1; i <= n; i ++){
 59             first[i] = -1;
 60             vis[i] = false;
 61             ring[i].clear();
 62             point[i] = emptyPoint;
 63         }
 64         while(!stk.empty()) stk.pop();
 65     }
 66     void addEdgeOneWay(int u, int v){
 67         edge[sign].to = v;
 68         edge[sign].next = first[u];
 69         first[u] = sign ++;
 70     }
 71     void tarjanAllPoint(){
 72         for(int i = 1; i <= sumOfPoint; i ++){
 73             if(!point[i].dfn){
 74                 tarjan(i);
 75             }
 76         }
 77     }
 78     vector<int> getAns(){
 79         vector<int> ans;
 80         int *outdegree = new int[sumOfPoint+1];
 81         for(int i = 1; i <= sumOfPoint; i ++){
 82             outdegree[i] = 0;
 83         }
 84         tarjanAllPoint();
 85         for(int i = 1; i <= sumOfPoint; i ++){
 86             for(int j = first[i]; j != -1; j = edge[j].next){
 87                 int to = edge[j].to;
 88                 if(point[to].color != point[i].color){
 89                     outdegree[point[i].color] ++;
 90                 }
 91             }
 92         }
 93         for(int i = 1; i <= colorNum; i ++){
 94             if(!outdegree[i]){
 95                 for(int j = 0; j < ring[i].size(); j ++){
 96                     ans.push_back(ring[i][j]);
 97                 }
 98             }
 99         }
100         sort(ans.begin(), ans.end());
101         delete []outdegree;
102         return ans;
103     }
104 }graph;
105 
106 int main(){
107     int n, m;
108     while(scanf("%d%d", &n, &m) != EOF && n){
109         graph.clear(n);
110         while(m --){
111             int a, b;
112             scanf("%d%d", &a, &b);
113             graph.addEdgeOneWay(a, b);
114         }
115         vector<int> ans = graph.getAns();
116         bool first = 1;
117         for(int i = 0; i < ans.size(); i ++){
118             if(first) first = 0;
119             else putchar(' ');
120             printf("%d", ans[i]);
121         }
122         putchar('\n');
123     }
124     return 0;
125 }

 

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