1. 程式人生 > >POJ 1470 -- Closest Common Ancestors

POJ 1470 -- Closest Common Ancestors

bre else common 多次提交 flag 變量 spa pro int

題目鏈接:http://poj.org/problem?id=1470 Closest Common Ancestors
Time Limit: 2000MS Memory Limit: 10000K
Total Submissions: 21483 Accepted: 6812

Description

Write a program that takes as input a rooted tree and a list of pairs of vertices. For each pair (u,v) the program determines the closest common ancestor of u and v in the tree. The closest common ancestor of two nodes u and v is the node w that is an ancestor of both u and v and has the greatest depth in the tree. A node can be its own ancestor (for example in Figure 1 the ancestors of node 2 are 2 and 5)

Input

The data set, which is read from a the std input, starts with the tree description, in the form:

nr_of_vertices
vertex:(nr_of_successors) successor1 successor2 ... successorn
...
where vertices are represented as integers from 1 to n ( n <= 900 ). The tree description is followed by a list of pairs of vertices, in the form:
nr_of_pairs
(u v) (x y) ...

The input file contents several data sets (at least one).
Note that white-spaces (tabs, spaces and line breaks) can be used freely in the input.

Output

For each common ancestor the program prints the ancestor and the number of pair for which it is an ancestor. The results are printed on the standard output on separate lines, in to the ascending order of the vertices, in the format: ancestor:times
For example, for the following tree:
技術分享圖片

Sample Input

5
5:(3) 1 4 2
1:(0)
4:(0)
2:(1) 3
3:(0)
6
(1 5) (1 4) (4 2)
      (2 3)
(1 3) (4 3)

Sample Output

2:1
5:5

Hint

Huge input, scanf is recommended. 題意:給出頂點數,各頂點的子節點數目和編號,詢問次數,每次詢問的頂點對,要求輸出詢問中出現的最近公共祖先和與其對應的詢問次數; 題解&總結: 1. LCA裸題,下面給出Tarjan離線解法的代碼,Tarjan算法網上已有許多不錯的講解,在此不再贅述,把dfs和並查集理解好Tarjan算法也就挺好理解了; 2. 輸入有多組數據,註意把數組和變量初始化; 3. 輸入的第一個數是節點數,不一定是根節點,根節點的確定應該通過排除子節點,剩下的一個就是根節點; 4. 代碼中以前向星來儲存邊,當然用vector來實現鄰接表也可以,但顯然前向星比vector更快; 5. 題目中只給出了最大節點數,但並沒有給出最大詢問次數,經多次提交實驗,最大詢問次數應該在250000左右,註意開足夠大的數組; 6. 通過此題可以發現,數組開小了不止可能會RE,還可能會訪問到垃圾數據使dfs無窮遞歸而MLE,也可能出現死循環而TLE; 7. 題目提示推薦用scanf輸入,本著倔強的精神試了cin輸入也還是可以1900+MS過了。 技術分享圖片
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <cstring>
 4 #define N 1010
 5 #define MAXQ 250010
 6 using namespace std;
 7 struct node{
 8     int next, to, lca;
 9 } edge[2*N], qedge[2*MAXQ];  // 儲存邊,依次儲存詢問
10 int num_edge, num_qedge, head[N], qhead[N];
11 int fa[N];
12 bool vis[N], flag[N];
13 void add_edge(int from, int to) { // 前向星添加邊
14     edge[++num_edge].next = head[from];
15     edge[num_edge].to = to;
16     head[from] = num_edge;
17 }
18 void add_qedge(int from, int to) {
19     qedge[++num_qedge].next = qhead[from];
20     qedge[num_qedge].to = to;
21     qhead[from] = num_qedge;
22 }
23 int Find(int x) {
24     if (fa[x] != x) fa[x] = Find(fa[x]);
25     return fa[x];
26 }
27 void dfs(int x) {
28     fa[x] = x;
29     vis[x] = true;
30     for (int k = head[x]; k; k = edge[k].next) {
31         if (!vis[edge[k].to]) {
32             dfs(edge[k].to);
33             fa[edge[k].to] = x;
34         }
35     }
36     for (int k = qhead[x]; k; k = qedge[k].next) {
37         if (vis[qedge[k].to]) {
38             qedge[k].lca = Find(qedge[k].to);
39             if (k & 1) qedge[k+1].lca = qedge[k].lca;
40             else qedge[k-1].lca = qedge[k].lca;
41         }
42     }
43 }
44 void init() {  // 初始化
45     memset(vis, false, sizeof(vis));
46     memset(flag, false, sizeof(flag));
47     memset(head, 0, sizeof(head));
48     memset(qhead, 0, sizeof(qhead));
49     num_edge = num_qedge = 0;
50 }
51 
52 int main() {
53     int n, x, y, k;
54     char ch;
55     ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
56     while (cin >> n) {
57         init();
58         for (int i = 0; i < n; i++) {
59             cin >> x >> ch >> ch >> k >> ch;//scanf("%d%*c%*c%d%*c", &x, &k);
60             while (k--) {
61                 cin >> y;//scanf(" %d", &y);
62                 flag[y] = true;
63                 add_edge(x, y); add_edge(y, x);
64             }
65 
66         }
67         cin >> k;//scanf("%d", &k);
68         for (int i = 0; i < k; i++) {
69             cin >> ch >> x >> y >> ch;//scanf(" %*c%d %d%*c", &x, &y);
70             add_qedge(x, y); add_qedge(y, x);
71         }
72         for (int i = 1; i <= n; i++) if (!flag[i]) dfs(i);  // 確定根節點
73         int cnt[N]; memset(cnt, 0, sizeof(cnt));
74         for (int i = 1; i <= k; i++) cnt[qedge[i*2].lca]++;
75         for (int i = 1; i <= n; i++) if (cnt[i]) cout << i << : << cnt[i] << endl;//printf("%d:%d\n", i, cnt[i]);
76     }
77 
78     return 0;
79 }
View Code

POJ 1470 -- Closest Common Ancestors