Hdu 4547 【最近公共祖先】.cpp

题意:

  dos命令的cd操作有两个可执行方法

  cd ..    回到上一级目录

  cd 当前目录名/b/c/d     当前目录名到某一个子目录下

  

  给出你目录的关系,然后给出a b问最少经过几步可以从a走到b..

 

思路:

  求出a和b的最近公共祖先,然后分4种情况讨论

  ①. a和b有一个公共祖先c,则用 c时间戳-a的时间戳+1(1步可以直接从c到b)

  ②. a是b的祖先,则只用1步就可以到达b点

  ③. b是a的祖先,则用a的时间戳-b的时间戳

  ④. a和b是同一个点,则答案是0

 

Tips:

  求绝对值的函数还是得自己写..

  用algorithm的就wa了..

  因为algorithm里面的fabs参数和返回值都是double的..

 

Code:

  1 #include <stdio.h>
  2 #include <cstring>
  3 #include <string>
  4 #include <iostream>
  5 #include <cmath>
  6 #include <map>
  7 using namespace std;
  8 
  9 const int MAXM = 10000010;
 10 const int MAXN = 100010;
 11 
 12 int f[MAXN];
 13 int find(int x)
 14 {
 15     return f[x] == x?x:f[x] = find(f[x]);
 16 }
 17 
 18 struct Edge
 19 {
 20     int s;
 21     int to;
 22     int next;
 23     int lca;
 24 }edge[MAXM], qedge[MAXM];
 25 int head[MAXN], qhead[MAXN];
 26 int tot, qtot;
 27 
 28 void add(int s, int u)
 29 {
 30     edge[tot].to = u;
 31     edge[tot].next = head[s];
 32     head[s] = tot++;
 33 }
 34 
 35 void qadd(int s, int u)
 36 {
 37     qedge[qtot].s = s;
 38     qedge[qtot].to = u;
 39     qedge[qtot].next = qhead[s];
 40     qhead[s] = qtot++;
 41     qedge[qtot].s = u;
 42     qedge[qtot].to = s;
 43     qedge[qtot].next = qhead[u];
 44     qhead[u] = qtot++;
 45 }
 46 
 47 bool vis[MAXN];
 48 int dfn[MAXN];
 49 int ti;
 50 void LCA(int u)
 51 {
 52     f[u] = u;
 53     vis[u] = true;
 54     for (int i = head[u]; i != -1; i = edge[i].next)
 55         if (!vis[edge[i].to]) {
 56             dfn[edge[i].to] = dfn[u]+1;
 57             LCA(edge[i].to);
 58             f[edge[i].to] = u;
 59         }
 60     for (int i = qhead[u]; i != -1; i = qedge[i].next) {
 61         if (vis[qedge[i].to]) {
 62             qedge[i].lca = find(qedge[i].to);
 63             qedge[i^1].lca = qedge[i].lca;
 64         }
 65     }
 66 }
 67 
 68 int abs(int x) {
 69     return x>0?x:-x;
 70 }
 71 
 72 int main()
 73 {
 74     int in[MAXN];
 75     int T, n, q;
 76     int cnt, fa;
 77     char str1[45], str2[45];
 78     scanf("%d", &T);
 79     while (T--) {
 80         scanf("%d %d", &n, &q);
 81         map<string, int> M;
 82         cnt = 1;
 83         tot = qtot = 0;
 84         ti = 0;
 85 
 86         memset(head, 0xff, sizeof(head));
 87         memset(qhead, 0xff, sizeof(qhead));
 88         for (int i = 0; i <= n; ++i) {
 89             f[i] = i;
 90             vis[i] = false;
 91             dfn[i] = 0;
 92             in[i] = 0;
 93         }
 94         for (int i = 0; i < n-1; ++i) {
 95             scanf("%s %s", str1, str2);
 96             if (!M[str1]) M[str1] = cnt++;
 97             if (!M[str2]) M[str2] = cnt++;
 98             add(M[str2], M[str1]);
 99             in[M[str1]]++;
100         }
101         for (int i = 0; i < q; ++i) {
102             scanf("%s %s", str1, str2);
103             qadd(M[str1], M[str2]);
104         }
105         for (int i = 1; i <= n; ++i)
106             if (in[i] == 0) {
107                 fa = i;
108                 break;
109             }
110         LCA(fa);
111 
112      //   for (int i = 1; i < cnt; ++i)
113      //       printf("___%d %d\n", i, dfn[i]);
114 
115         for (int i = 0; i < qtot; ++i)
116         if (i%2 == 0) {
117           //  printf("%d %d___ %d\n", qedge[i].s, qedge[i].to, qedge[i].lca);
118          //   printf("%d_____\n", qedge[i].lca);
119        //  printf("___%d %d\n", dfn[qedge[i].s], dfn[qedge[i].lca]);
120             if (qedge[i].to == qedge[i].s) puts("0");
121             else if (qedge[i].lca == qedge[i].to) printf("%d\n", abs(dfn[qedge[i].s]-dfn[qedge[i].to]));
122             else if (qedge[i].s == qedge[i].lca) puts("1");
123             else printf("%d\n", abs(dfn[qedge[i].s]-dfn[qedge[i].lca])+1);
124         }
125     }
126     return 0;
127 }
View Code

 

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4547

posted @ 2013-06-05 17:03  Griselda.  阅读(871)  评论(0编辑  收藏  举报