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 }