NBUT 2014 C Lord of Minecraft

题目链接:http://acm.nbut.edu.cn/problem/view.xhtml?id=1554

题意:给出一个n(\(n\leq 10000\))个节点的树,然后给出m(\(m\leq100000\))个询问,每个询问给出两个节点x和y,问从x到y的路径是否经过与x深度相同的节点?

分析:

用depth[k]表示标号为k的节点在树中的深度

(1) 如果depth[x]>depth[y],显然不经过;如果depth[x]==depth[y],显然经过;如果depth[x]<depth[y],如果x是y的祖先节点,则不经过否则经过;

(2) 根据(1),可以先计算出每个节点的深度,就能通过比较深度搞定询问中的前两种情况。对于depth[x]<depth[y],需要判断x是否为y的祖先

(3) 这里不需要求出x,y的lca,只需要判断depth[x]<depth[y]时、x是否为y的祖先即可,显然dfs就可以做到,如果则x是y的祖先,那么dfs遍历到y时,x应该在栈中。

(4) 可以离线操作:将询问中节点y对应的所有x放入y的队列中,当遍历到y时,直接判断x是否在栈中即可

(5) 标程采用了另一中做法:按照dfs遍历的顺序维护一个标号flag,dfs时记录每个节点的标号范围,即进入一个节点x时l[x]=falg++,出x时r[x]=flag++,那么[ l[x], r[x] ]就是x的子孙的标号范围,这样通过比较范围可以确定x是否为y的祖先。

题目给出的节点是字符串类型的,用map映射到int型

 

 1 # include <cstdio>
 2 # include <cstring>
 3 # include <map>
 4 # include <vector>
 5 # include <string>
 6 using namespace std;
 7 
 8 const int maxn = 10005;
 9 
10 int n, m;
11 map <string, int> mp;
12 int root;
13 vector <int> G[maxn];
14 vector <int> Q[maxn];
15 int d[maxn];
16 
17 char x[15], y[15];
18 string sx, sy;
19 
20 int id;
21 int ans;
22 
23 bool ins[maxn];
24 void dfs_solve(int cur)
25 {
26     ins[cur] = true;
27     for (int i = 0; i < Q[cur].size(); ++i) {
28         if (ins[ Q[cur][i] ] == false) ++ans;
29     }
30     for (int i = 0; i < G[cur].size(); ++i) dfs_solve(G[cur][i]);
31   ins[cur] = false;
32 }
33 void dfs_depth(int cur, int depth)
34 {
35     d[cur] = depth;
36     for (int i = 0; i < G[cur].size(); ++i) dfs_depth(G[cur][i], depth+1);
37 }
38 int add(const string &s)
39 {
40     int ret = mp[s];
41     if (ret < 1) ret = (mp[s] = ++id);
42     return ret;
43 }
44 
45 int main()
46 {
47     while (EOF != scanf("%d%d", &n, &m)) {
48         mp.clear();
49         for (int i = 1; i <= n+1; ++i) G[i].clear();
50         id = 0;
51         for (int i = 0; i < n; ++i) {
52             scanf("%s%s", x, y);
53             sx = x, sy = y;
54             int ix = add(sx);
55             int iy = add(sy);
56             if (strcmp(y, "Hungar") == 0) root = iy;
57             G[iy].push_back(ix);
58         }
59         for (int i = 1; i <= id; ++i) d[i] = 0;
60         dfs_depth(root, 0);
61         ans = 0;
62         for (int i = 1; i <= id; ++i) Q[i].clear();
63         for (int i = 0; i < m; ++i) {
64             scanf("%s%s", x, y);
65             sx = x, sy = y;
66             int ix = mp[sx];
67             int iy = mp[sy];
68             if (d[ix] < d[iy]) Q[iy].push_back(ix);
69             else if (d[ix] == d[iy]) ++ans;
70         }
71         for (int i = 1; i <= id; ++i) ins[i] = false;
72         dfs_solve(root);
73         printf("%d\n", ans);
74     }
75 
76     return 0;
77 }
1

 

 1 # include <cstdio>
 2 # include <cstring>
 3 # include <string>
 4 # include <map>
 5 # include <vector>
 6 using namespace std;
 7 
 8 const int maxn = 10005;
 9 
10 int n, m;
11 map <string, int> mp;
12 vector <int> G[maxn];
13 int d[maxn];
14 int l[maxn], r[maxn];
15 int id, root;
16 char sx[15], sy[15];
17 string stx, sty;
18 int cnt;
19 void dfs(int cur, int depth)
20 {
21     d[cur] = depth;
22     l[cur] = cnt++;
23     for (int i = 0; i < G[cur].size(); ++i) dfs(G[cur][i], depth+1);
24     r[cur] = cnt++;
25 }
26 
27 int add(const string &s)
28 {
29     return mp[s]>0 ? mp[s]:(mp[s]=++id);
30 }
31 
32 void init(void)
33 {
34     id = 0;
35     mp.clear();
36     for (int i = 1; i <= n+1; ++i) G[i].clear();
37     for (int i = 0; i < n; ++i) {
38         scanf("%s%s", sx, sy); stx = sx, sty = sy;
39         int x = add(stx), y = add(sty);
40         if (strcmp(sy, "Hungar") == 0) root = y;
41         G[y].push_back(x);
42     }
43     cnt = 0;
44     dfs(root, 0);
45 }
46 
47 void solve(void)
48 {
49     int ans = 0;
50     for (int i = 0; i < m; ++i) {
51         scanf("%s%s", sx, sy);
52         stx = sx, sty = sy;
53         int x = mp[stx];
54         int y = mp[sty];
55         if ((d[x]<d[y] && !(l[x]<l[y] && r[y]<r[x])) || (d[x]==d[y])) ++ans;
56     }
57     printf("%d\n", ans);
58 }
59 
60 int main()
61 {
62     while (EOF != scanf("%d%d", &n, &m)) {
63         init();
64         solve();
65     }
66     return 0;
67 }
2

 

posted @ 2014-05-06 13:55  努力变瘦  阅读(153)  评论(0编辑  收藏  举报