首页 > 代码库 > HDU 4547 LCA倍增算法
HDU 4547 LCA倍增算法
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操作才能将当前目录变成目标目录?
这里我们简化一下问题,假设只有一个根目录,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操作。
数据保证合法,一定存在一个根目录,每个目录都能从根目录访问到。
每个样例首先一行是两个整数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 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。