码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 4547 LCA倍增算法

时间:2014-08-12 18:21:04      阅读:217      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   color   java   os   io   strong   

CD操作

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 1111    Accepted Submission(s): 297


Problem Description
  在Windows下我们可以通过cmd运行DOS的部分功能,其中CD是一条很有意思的命令,通过CD操作,我们可以改变当前目录。
  这里我们简化一下问题,假设只有一个根目录,CD操作也只有两种方式:
  
  1. CD 当前目录名\...\目标目录名 (中间可以包含若干目录,保证目标目录通过绝对路径可达)
  2. CD .. (返回当前目录的上级目录)
  
  现在给出当前目录和一个目标目录,请问最少需要几次CD操作才能将当前目录变成目标目录?
 

 

Input
输入数据第一行包含一个整数T(T<=20),表示样例个数;
每个样例首先一行是两个整数N和M(1<=N,M<=100000),表示有N个目录和M个询问;
接下来N-1行每行两个目录名A B(目录名是只含有数字或字母,长度小于40的字符串),表示A的父目录是B。
最后M行每行两个目录名A B,表示询问将当前目录从A变成B最少要多少次CD操作。
数据保证合法,一定存在一个根目录,每个目录都能从根目录访问到。
 

 

Output
请输出每次询问的结果,每个查询的输出占一行。
 

 

Sample Input
2
3 1
B A
C A
B C
3 2
B A
C B
A C
C A
 

 

Sample Output
2
1
2
 
 
 
 
用map存储字符串,然后每输入一对字符串A、B,就找它们的最近公共祖先C,然后有4种情况:
1、A==B  则输出0
2、C!=A&&C!=B   则输出A到C的距离再加上1(1是从C到B,由题目知从一目录到该目录包含的所有目录走1步即可)
3、C==A   则直接输出1
4、C==B   则输出A到B的距离
 
 
代码:
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <map>
  5 #include <vector>
  6 #include <queue>
  7 #include <iostream>
  8 using namespace std;
  9 #define N 100005
 10 #define M 20
 11 
 12 int dep[N];
 13 int f[N][M];
 14 int visited[N];
 15 map<string,int>ma;
 16 int n, m;
 17 vector<int>ve[N];
 18 
 19 
 20 void init()
 21 {
 22     memset(dep,0,sizeof(dep));
 23     memset(f,0,sizeof(f));
 24     memset(visited,0,sizeof(visited));
 25     ma.clear();
 26     for(int i=0;i<=n;i++) ve[i].clear();
 27 }
 28 
 29 void bfs(int root){
 30     queue<int>Q;
 31     int i, u;
 32     Q.push(root);
 33     while(!Q.empty()){
 34         u=Q.front();
 35         Q.pop();
 36         if(visited[u]) continue;
 37         visited[u]=1;
 38         dep[u]=dep[f[u][0]]+1;
 39         for(i=1;i<M;i++) f[u][i]=f[f[u][i-1]][i-1];
 40         for(i=0;i<ve[u].size();i++) Q.push(ve[u][i]);
 41     }
 42 }
 43 
 44 int lca(int x,int y){
 45     if(dep[x]<dep[y]) swap(x,y);
 46     int i, k=dep[x]-dep[y];
 47     for(i=0;i<M;i++){
 48         if(1<<i&k){
 49             x=f[x][i];
 50         }
 51     }
 52     if(x==y) return x;
 53     for(i=M-1;i>=0;i--){
 54         if(f[x][i]!=f[y][i]){
 55             x=f[x][i];
 56             y=f[y][i];
 57         }
 58     }
 59     return f[x][0];
 60 }
 61 
 62 main()
 63 {
 64     int i, j;
 65     int k;
 66     string s1, s2;
 67     int t;
 68     cin>>t;
 69     while(t--){
 70         init();
 71         scanf("%d %d",&n,&m);
 72         k=1;
 73         for(i=1;i<n;i++){
 74             cin>>s1>>s2;
 75             if(ma.find(s1)==ma.end()){
 76                 ma[s1]=k++;
 77             }
 78             if(ma.find(s2)==ma.end()){
 79                 ma[s2]=k++;
 80             }
 81             f[ma[s1]][0]=ma[s2];
 82             ve[ma[s2]].push_back(ma[s1]);
 83         }
 84         int root;
 85         for(i=1;i<=n;i++){
 86             if(!f[i][0]){
 87                 root=i;break;
 88             }
 89         }
 90         bfs(root);
 91         while(m--){
 92             cin>>s1>>s2;
 93             int node=lca(ma[s1],ma[s2]);
 94             if(ma[s1]==ma[s2]){
 95                 printf("0\n");
 96             }
 97             else if(node!=ma[s1]&&node!=ma[s2]) printf("%d\n",dep[ma[s1]]-dep[node]+1);
 98             else if(node==ma[s1]) printf("1\n");
 99             else if(node==ma[s2]) printf("%d\n",dep[ma[s1]]-dep[ma[s2]]);
100         }
101         
102     }
103 }

 

HDU 4547 LCA倍增算法,布布扣,bubuko.com

HDU 4547 LCA倍增算法

标签:des   style   blog   color   java   os   io   strong   

原文地址:http://www.cnblogs.com/qq1012662902/p/3907527.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!