zoukankan      html  css  js  c++  java
  • 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("*****
    ");
     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
    ",ans);
    168         }
    169     }
    170 }
  • 相关阅读:
    十大佛教经典语,你最中意哪一句
    哲理人生名句, 拿个本子记下来
    逸乐有节 不可过度
    教你怎么用59秒就能打动客户?
    爱的意义
    一个聪明女人写的日记(转)
    做人做事十三条铁则
    爱上一个人的7个征兆
    办公室白领须知的18个定律
    生活智慧:奇特的人生法则
  • 原文地址:https://www.cnblogs.com/cnblogs321114287/p/4570950.html
Copyright © 2011-2022 走看看