|
| 1 | +/* |
| 2 | +
|
| 3 | + Name: Mehul Chaturvedi |
| 4 | + IIT-Guwahati |
| 5 | +
|
| 6 | +*/ |
| 7 | +/* |
| 8 | +We will use the following (standard) definitions from graph theory. Let V be a non-empty and finite set, its elements being called vertices (or nodes). Let E be a subset of the Cartesian product V×V, its elements being called edges. Then G=(V,E) is called a directed graph. |
| 9 | +
|
| 10 | +Let n be a positive integer, and let p=(e1,…,en) be a sequence of length n of edges ei∈E such that ei=(vi,vi+1)for a sequence of vertices (v1,…,vn+1). Then p is called a path from vertex v1 to vertex vn+1 in G and we say that vn+1 is reachable from v1, writing (v1→vn+1). |
| 11 | +
|
| 12 | +Here are some new definitions. A node v in a graph G=(V,E) is called a sink, if for every node w in G that is reachable from v, v is also reachable from w. The bottom of a graph is the subset of all nodes that are sinks, i.e., bottom(G)={v∈V∣∀w∈V:(v→w)⇒(w→v)}. You have to calculate the bottom of certain graphs. |
| 13 | +Input Specification |
| 14 | +The input contains several test cases, each of which corresponds to a directed graph G. Each test case starts with an integer number v, denoting the number of vertices of G=(V,E) where the vertices will be identified by the integer numbers in the set V={1,…,v}. You may assume that 1≤v≤5000. That is followed by a non-negative integer e and, thereafter, e pairs of vertex identifiers v1,w1,…,ve,we with the meaning that (vi,wi)∈E. There are no edges other than specified by these pairs. The last test case is followed by a zero. |
| 15 | +Output Specification |
| 16 | +For each test case output the bottom of the specified graph on a single line. To this end, print the numbers of all nodes that are sinks in sorted order separated by a single space character. If the bottom is empty, print an empty line. |
| 17 | +Sample Input |
| 18 | +3 3 |
| 19 | +1 3 2 3 3 1 |
| 20 | +2 1 |
| 21 | +1 2 |
| 22 | +0 |
| 23 | +Sample Output |
| 24 | +1 3 |
| 25 | +2 |
| 26 | +*/ |
| 27 | + |
| 28 | +#include <bits/stdc++.h> |
| 29 | +using namespace std; |
| 30 | + |
| 31 | +typedef long long ll; |
| 32 | +typedef unordered_map<int, int> umapii; |
| 33 | +typedef unordered_map<int, bool> umapib; |
| 34 | +typedef unordered_map<string, int> umapsi; |
| 35 | +typedef unordered_map<string, string> umapss; |
| 36 | +typedef map<string, int> mapsi; |
| 37 | +typedef map<pair<int, int>, int> mappiii; |
| 38 | +typedef map<int, int> mapii; |
| 39 | +typedef pair<int, int> pii; |
| 40 | +typedef pair<long long, long long> pll; |
| 41 | +typedef unordered_set<int> useti; |
| 42 | + |
| 43 | +#define uset unordered_set |
| 44 | +#define it iterator |
| 45 | +#define mp make_pair |
| 46 | +#define pb push_back |
| 47 | +#define all(x) (x).begin(), (x).end() |
| 48 | +#define f first |
| 49 | +#define s second |
| 50 | +#define MOD 1000000007 |
| 51 | + |
| 52 | +void dfs2(int start, vector<int>* edgest, int* visited, unordered_set<int>* component){ |
| 53 | + visited[start] = 1; |
| 54 | + component->insert(start); |
| 55 | + |
| 56 | + for (int i = 0; i < edgest[start].size(); ++i) |
| 57 | + { |
| 58 | + if (visited[edgest[start].at(i)]==0) |
| 59 | + { |
| 60 | + dfs2(edgest[start].at(i), edgest, visited, component); |
| 61 | + } |
| 62 | + } |
| 63 | + |
| 64 | + return; |
| 65 | +} |
| 66 | + |
| 67 | +void dfs(vector<int>* edges, int start, int* visited, stack<int> &s){ |
| 68 | + visited[start] = 1; |
| 69 | + for (int i = 0; i < edges[start].size(); ++i) |
| 70 | + { |
| 71 | + if (visited[edges[start].at(i)] == 0) |
| 72 | + { |
| 73 | + dfs(edges, edges[start].at(i), visited, s); |
| 74 | + } |
| 75 | + } |
| 76 | + |
| 77 | + s.push(start); |
| 78 | + |
| 79 | + return; |
| 80 | +} |
| 81 | + |
| 82 | +unordered_set<unordered_set<int>*>* kosaraju(vector<int>* edges, vector<int>* edgest, int v){ |
| 83 | + //Initialize an empty set of sets for the answer |
| 84 | + unordered_set<unordered_set<int>*>* ans = new unordered_set<unordered_set<int>*>(); |
| 85 | + |
| 86 | + stack<int> s; |
| 87 | + int* visited = new int[v]; |
| 88 | + for (int i = 0; i < v; ++i) |
| 89 | + { |
| 90 | + visited[i] = 0; |
| 91 | + } |
| 92 | + |
| 93 | + for (int i = 0; i < v; ++i) |
| 94 | + { |
| 95 | + if (visited[i] == 0) |
| 96 | + { |
| 97 | + dfs(edges, i, visited, s); |
| 98 | + } |
| 99 | + |
| 100 | + } |
| 101 | + |
| 102 | + |
| 103 | + for (int i = 0; i < v; ++i) |
| 104 | + { |
| 105 | + visited[i] = 0; |
| 106 | + } |
| 107 | + |
| 108 | + // while(!s.empty()){ |
| 109 | + // cout << s.top() << '\n'; |
| 110 | + // s.pop(); |
| 111 | + // } |
| 112 | + |
| 113 | + //return ans; |
| 114 | + while(!s.empty()){ |
| 115 | + int t = s.top(); |
| 116 | + s.pop(); |
| 117 | + |
| 118 | + |
| 119 | + if (visited[t] == 0) |
| 120 | + { |
| 121 | + |
| 122 | + unordered_set<int>* component = new unordered_set<int>(); |
| 123 | + dfs2(t, edgest, visited, component); |
| 124 | + ans->insert(component); |
| 125 | + }else{ |
| 126 | + continue; |
| 127 | + } |
| 128 | + } |
| 129 | + |
| 130 | + return ans; |
| 131 | + |
| 132 | +} |
| 133 | + |
| 134 | +int main( int argc , char ** argv ) |
| 135 | +{ |
| 136 | + ios_base::sync_with_stdio(false) ; |
| 137 | + cin.tie(NULL) ; |
| 138 | + |
| 139 | + while(1){ |
| 140 | + int v, e; |
| 141 | + cin>>v; |
| 142 | + if (v==0) |
| 143 | + { |
| 144 | + break; |
| 145 | + } |
| 146 | + cin>>e; |
| 147 | + vector<int>* edges = new vector<int>[v]; |
| 148 | + vector<int>* edgest = new vector<int>[v]; |
| 149 | + |
| 150 | + for (int i = 0; i < e; ++i) |
| 151 | + { |
| 152 | + int a, b; |
| 153 | + cin>>a>>b; |
| 154 | + |
| 155 | + edges[a-1].push_back(b-1); |
| 156 | + edgest[b-1].push_back(a-1); |
| 157 | + } |
| 158 | + |
| 159 | + unordered_set<unordered_set<int>*>* components = kosaraju(edges, edgest, v); |
| 160 | + |
| 161 | + auto it = components->begin(); |
| 162 | + while(it!=components->end()){ |
| 163 | + auto it2 = (*it)->begin(); |
| 164 | + while(it2!=(*it)->end()){ |
| 165 | + int i = 0; |
| 166 | + for (i = 0; i < edges[*it2].size(); ++i) |
| 167 | + { |
| 168 | + if (it->count(edges[*it2].at(i)) == 0) |
| 169 | + { |
| 170 | + break; |
| 171 | + } |
| 172 | + } |
| 173 | + if (i==edges[*it2].size()) |
| 174 | + { |
| 175 | + break; |
| 176 | + } |
| 177 | + it2++; |
| 178 | + } |
| 179 | + while(it2!=(*it)->end()){ |
| 180 | + cout << *it2 << ' '; |
| 181 | + } |
| 182 | + cout <<'\n'; |
| 183 | + it++; |
| 184 | + } |
| 185 | + } |
| 186 | + |
| 187 | + |
| 188 | + |
| 189 | + return 0 ; |
| 190 | + |
| 191 | + |
| 192 | + |
| 193 | +} |
0 commit comments