1008. Airline Routes (35)解题报告
2017-01-17 02:10
309 查看
首先感谢神赐予我智慧和力量。
我先通过DFS把图分解为若干个强连通分量,然后用并查集区分每个强连通分量。查询时,只要找并查集的根就可以了。这种方法来自《算法导论》22.5强连通分量。划分强连通分量的时间复杂度为O(V+E),查询的时间复杂度为O(K)。
用DFS标记出每个结点的结束时间。
按照结束时间降序,对逆邻接表进行DFS。
单独一次DFS所遍历的结点就是某一个强连通分量的所有成员。
在第二次DFS时,把同一个强连通分量的结点归并到同一个集合里。
在解题过程中,我也参阅了下面这篇博文:
PAT (Top Level) Practise 1008 Airline Routes (35) - 程序园
我先通过DFS把图分解为若干个强连通分量,然后用并查集区分每个强连通分量。查询时,只要找并查集的根就可以了。这种方法来自《算法导论》22.5强连通分量。划分强连通分量的时间复杂度为O(V+E),查询的时间复杂度为O(K)。
用DFS标记出每个结点的结束时间。
按照结束时间降序,对逆邻接表进行DFS。
单独一次DFS所遍历的结点就是某一个强连通分量的所有成员。
在第二次DFS时,把同一个强连通分量的结点归并到同一个集合里。
在解题过程中,我也参阅了下面这篇博文:
PAT (Top Level) Practise 1008 Airline Routes (35) - 程序园
#define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <cstdlib> #include <cstring> #include <vector> #include <stack> using namespace std; const int N = 10003; void dfs(vector<int> city[], int index); void dfs(vector<int> city[], int index, int cityset[]); int findroot(int cityset[], int index); void setunion(int cityset[], int index1, int index2); stack<int> s; bool visit ; int finish ; int main(void) { int n, m, k, i, source, dest, *cityset; vector<int> *city, *cityt; setvbuf(stdin, new char[1 << 20], _IOFBF, 1 << 20); setvbuf(stdout, new char[1 << 20], _IOFBF, 1 << 20); scanf("%d %d", &n, &m); cityset = new int[n + 1]; city = new vector<int>[n + 1]; cityt = new vector<int>[n + 1]; for (i = 0; i < n + 1; i++) { cityset[i] = -1; } for (i = 0; i < m; i++) { scanf("%d %d", &source, &dest); city[source].push_back(dest); cityt[dest].push_back(source); } for (i = 1; i <= n; i++) { if (!visit[i]) { dfs(city, i); } } memset(visit, 0, N * sizeof(bool)); for (i = n; i > 0; i--) { if (!visit[finish[i]]) { dfs(cityt, finish[i], cityset); } } scanf("%d", &k); for (i = 0; i < k; i++) { scanf("%d %d", &source, &dest); int root1 = findroot(cityset, source), root2 = findroot(cityset, dest); if (root1 != -1 && root1 == root2) { puts("Yes"); } else { puts("No"); } } delete[] city; delete[] cityt; delete[] cityset; return 0; } void dfs(vector<int> city[], int index, int cityset[]) { int i; visit[index] = true; s.push(index); for (i = 0; i < (int) city[index].size(); i++) { if (!visit[city[index][i]]) { setunion(cityset, index, city[index][i]); dfs(city, city[index][i], cityset); } } s.pop(); return; } void dfs(vector<int> city[], int index) { int i; static int cnt = 0; visit[index] = true; s.push(index); for (i = 0; i < (int) city[index].size(); i++) { if (!visit[city[index][i]]) { dfs(city, city[index][i]); } } cnt++; finish[cnt] = index; s.pop(); return; } int findroot(int cityset[], int index) { if (cityset[index] < 0) { return index; } else { return cityset[index] = findroot(cityset, cityset[index]); } } void setunion(int cityset[], int index1, int index2) { int root1, root2; root1 = findroot(cityset, index1); root2 = findroot(cityset, index2); if (root1 == root2) { return; } if (cityset[root1] < cityset[root2]) { cityset[root1] += cityset[root2]; cityset[root2] = root1; } else { cityset[root2] += cityset[root1]; cityset[root1] = root2; } return; }
相关文章推荐
- 1015. Letter-moving Game (35)解题报告
- 1016. Uniqueness of MST (35)解题报告
- 1017. The Best Peak Shape (35)解题报告
- 1005. Programming Pattern (35)解题报告
- 1002. Business (35)解题报告
- 1009. Triple Inversions (35)解题报告
- 1007. Red-black Tree (35)解题报告
- 1001. Battle Over Cities - Hard Version (35)解题报告
- 1004. To Buy or Not to Buy - Hard Version (35)解题报告
- 1003. Universal Travel Sites (35)解题报告
- 1011. Cut Rectangles (35)解题报告
- 1006. Tree Traversals - Hard Version (35)解题报告
- 1012. Greedy Snake (35)解题报告
- RQNOJ 35 营救 解题报告
- 1013. Image Segmentation (35)解题报告
- 剑指Offer 面试题35:第一个只出现一次的字符 解题报告(华为OJ034-找出字符串中第一个只出现一次的字符)
- 1014. Circles of Friends (35)解题报告
- 1010. Lehmer Code (35)解题报告
- POJ 2243解题报告
- Sicily 1375. Balanced lineup 解题报告