hdu 4547 LCA **

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

链接:点我

先返回到根目录,然后直接前进到目标目录

目录刚好成一颗树。
树有唯一的根结点。
每步操作可以到上一级目录,或者直接到下面的目录。
 
其实就是查询LCA
 
要求u->v
把u、v的lca求出来,设为tmp
那么肯定是先u->tmp->u
 
u->temp的步数刚好是他们的深度差,一个数组存深度差就可以了。
 
temp->v如果不相等就是一步,相等就是0步
  1 #include <iostream>
  2 #include <string.h>
  3 #include <algorithm>
  4 #include <queue>
  5 #include <map>
  6 #include <vector>
  7 #include <math.h>
  8 #include <string>
  9 #include <stdio.h>
 10 #include <math.h>
 11 using namespace std;
 12 #define MOD 1000000007
 13 #define pb(a) push_back(a)
 14 const int INF=0x3f3f3f3f;
 15 const double eps=1e-5;
 16 typedef long long ll;
 17 #define cl(a) memset(a,0,sizeof(a))
 18 #define ts printf("*****\n");
 19 const int MAXN=100010;
 20 int n,m,ttt;
 21 int a[MAXN];
 22 int rmq[2*MAXN];//rmq数组,就是欧拉序列对应的深度序列
 23 struct ST
 24 {
 25     int mm[2*MAXN];
 26     int dp[2*MAXN][20];//最小值对应的下标
 27     void init(int n)
 28     {
 29         mm[0] = -1;
 30         for(int i = 1;i <= n;i++)
 31         {
 32         mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1];
 33         dp[i][0] = i;
 34         }
 35         for(int j = 1; j <= mm[n];j++)
 36         for(int i = 1; i + (1<<j) - 1 <= n; i++)
 37         dp[i][j] = rmq[dp[i][j-1]] < rmq[dp[i+(1<<(j-1))][j-1]]?dp[i][j-1]:dp[i+(1<<(j-1))][j-1];
 38     }
 39     int query(int a,int b)//查询[a,b]之间最小值的下标
 40     {
 41         if(a > b)swap(a,b);
 42         int k = mm[b-a+1];
 43         return rmq[dp[a][k]] <= rmq[dp[b-(1<<k)+1][k]]?dp[a][k]:dp[b-(1<<k)+1][k];
 44     }
 45 };
 46 //边的结构体定义
 47 struct Edge
 48 {
 49     int to,next;
 50 };
 51 Edge edge[MAXN*2];
 52 int tot,head[MAXN];
 53 int F[MAXN*2];//欧拉序列,就是dfs遍历的顺序,长度为2*n-1,下标从1开始
 54 int P[MAXN];//P[i]表示点i在F中第一次出现的位置
 55 int cnt;
 56 ST st;
 57 void init()
 58 {
 59     tot = 0;
 60     memset(head,-1,sizeof(head));
 61 }
 62 void addedge(int u,int v)//加边,无向边需要加两次
 63 {
 64     edge[tot].to = v;
 65     edge[tot].next = head[u];
 66     head[u] = tot++;
 67 }
 68 void dfs(int u,int pre,int dep)
 69 {
 70     F[++cnt] = u;
 71     rmq[cnt] = dep;
 72     P[u] = cnt;
 73     for(int i = head[u];i != -1;i = edge[i].next)
 74     {
 75         int v = edge[i].to;
 76         if(v == pre)continue;
 77         dfs(v,u,dep+1);
 78         F[++cnt] = u;
 79         rmq[cnt] = dep;
 80     }
 81 }
 82 void LCA_init(int root,int node_num)//查询LCA前的初始化
 83 {
 84     cnt = 0;
 85     dfs(root,root,0);
 86     st.init(2*node_num-1);
 87 }
 88 int query_lca(int u,int v)//查询u,v的lca编号
 89 {
 90     return F[st.query(P[u],P[v])];
 91 }
 92 bool flag[MAXN];
 93 int Count_num[MAXN];
 94 int deep[MAXN];
 95 vector<int>vc[MAXN];
 96 map<string,int> mp;
 97 void bfs(int root)
 98 {
 99     cl(deep);
100     int now,next;
101     queue<int> q;
102     q.push(root);
103     deep[root]=1;
104     while(!q.empty())
105     {
106         now=q.front();
107         q.pop();
108         for(int i=0;i<vc[now].size();i++)
109         {
110             next=vc[now][i];
111             if(deep[next]==0)
112             {
113                 deep[next]=deep[now]+1;
114                 q.push(next);
115             }
116         }
117 
118     }
119 }
120 int main()
121 {
122     int i,j,k;
123     #ifndef ONLINE_JUDGE
124     freopen("1.in","r",stdin);
125     #endif
126     scanf("%d",&ttt);
127     int ca=1;
128     while(ttt--)
129     {
130         scanf("%d%d",&n,&m);
131         cl(flag);
132         init();
133         for(int i=0;i<=n;i++)vc[i].clear();
134         string u,v;
135         mp.clear();
136         int tot=0;
137         char s1[5],s2[5];
138         for(i=0;i<n-1;i++)
139         {
140             cin>>u>>v;
141             if(mp[u]==0)    mp[u]=++tot;
142             if(mp[v]==0)    mp[v]=++tot;
143             int a1=mp[u];
144             int a2=mp[v];
145             vc[a2].pb(a1);
146             addedge(a2,a1);
147             addedge(a1,a2);
148             flag[a1]=1;
149         }
150         int root;
151         for(int i=1;i<=n;i++)
152             if(!flag[i])
153             {
154                 root=i;
155                 break;
156             }
157         LCA_init(root,n);
158         bfs(root);
159         for(i=0;i<m;i++)
160         {
161             cin>>u>>v;
162             int a1=mp[u];
163             int a2=mp[v];
164             int temp=query_lca(a1,a2);
165             int ans=deep[a1]-deep[temp];
166             if(temp!=a2) ans++;
167             printf("%d\n",ans);
168         }
169     }
170 }

 

posted @ 2015-06-12 09:54  miao_a_miao  阅读(149)  评论(0编辑  收藏  举报