0


P10289 [GESP样题 八级] 小杨的旅游

Description

给定一棵

     n 
    
   
  
    n 
   
  
n 个点的树,每条边权值均为  
 
  
   
   
     1 
    
   
  
    1 
   
  
1,树上有  
 
  
   
   
     k 
    
   
  
    k 
   
  
k 个关键点,关键点们在  
 
  
   
   
     0 
    
   
  
    0 
   
  
0 的时间内相互可达, 
 
  
   
   
     q 
    
   
  
    q 
   
  
q 次询问,求  
 
  
   
   
     s 
    
   
     → 
    
   
     t 
    
   
  
    s\to t 
   
  
s→t 的最短路。

Analysis

考虑暴力建图,则图上共有

     ( 
    
   
     n 
    
   
     − 
    
   
     1 
    
   
     + 
    
    
     
     
       n 
      
     
       ( 
      
     
       n 
      
     
       − 
      
     
       1 
      
     
       ) 
      
     
    
      2 
     
    
   
     ) 
    
   
  
    (n-1+\frac{n(n-1)}{2}) 
   
  
(n−1+2n(n−1)​)条边,在  
 
  
   
   
     n 
    
   
     , 
    
   
     k 
    
   
  
    n,k 
   
  
n,k 均为最大的情况下,图上共有大约  
 
  
   
   
     2 
    
   
     × 
    
   
     1 
    
    
    
      0 
     
    
      10 
     
    
   
  
    2 \times 10^{10} 
   
  
2×1010 条边,铁定 
MLE

我们注意到,从

     s 
    
   
  
    s 
   
  
s 到  
 
  
   
   
     t 
    
   
  
    t 
   
  
t 只有两种情况:
  • 老老实实从树上走;
  • 从 s s s 走到一个关键点 k 1 k_1 k1​,穿越到另一个关键点 k 2 k_2 k2​,再走到 t t t。

第一种情况就是常规树上两点最短路。
第二种情况,根据贪心思想,选取的

      k 
     
    
      1 
     
    
   
     , 
    
    
    
      k 
     
    
      2 
     
    
   
  
    k_1,k_2 
   
  
k1​,k2​ 一定是距离  
 
  
   
   
     s 
    
   
     , 
    
   
     t 
    
   
  
    s,t 
   
  
s,t 最近的两个。所以我们初始时一次 
bfs

求出每个点

     i 
    
   
  
    i 
   
  
i 到传送门的距离  
 
  
   
   
     d 
    
   
     s 
    
    
    
      t 
     
    
      i 
     
    
   
  
    dst_i 
   
  
dsti​,最终答案即为  
 
  
   
   
     d 
    
   
     s 
    
    
    
      t 
     
    
      s 
     
    
   
     + 
    
   
     d 
    
   
     s 
    
    
    
      t 
     
    
      t 
     
    
   
  
    dst_s+dst_t 
   
  
dsts​+dstt​。

Code

// Problem: P10289 [GESP样题 八级] 小杨的旅游// Contest: Luogu// URL: https://www.luogu.com.cn/problem/P10289// Memory Limit: 512 MB// Time Limit: 1000 ms// // Powered by CP Editor (https://cpeditor.org)#include<iostream>#include<queue>#include<cmath>usingnamespace std;using Graph = vector<vector<int>>;constint INF =1e9;structLCA{int n, k;
    vector<int> dep;
    vector<vector<int>> f;
    Graph G;LCA(){}LCA(const Graph &tree):G(tree){
        n = G.size();
        k =(int)log2(n)+1;
        
        dep.assign(n,0);
        f.assign(n,vector<int>(k,-1));dfs(0,0);}voiddfs(int u,int fa){
        dep[u]= dep[fa]+1;
        f[u][0]= fa;for(int i =1; i < k; i++) f[u][i]= f[f[u][i -1]][i -1];for(auto v: G[u]){if(v == fa)continue;dfs(v, u);}}intlca(int x,int y){if(dep[x]< dep[y])swap(x, y);for(int i = k -1; i >=0; i--)if(dep[f[x][i]]>= dep[y]) x = f[x][i];if(x == y)return x;for(int i = k -1; i >=0; i --)if(f[x][i]!= f[y][i]){
                x = f[x][i];
                y = f[y][i];}return f[x][0];}intdist(int x,int y){return dep[x]+ dep[y]-2* dep[lca(x, y)];}};signedmain(){
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);int n, k, q;
    cin >> n >> k >> q;
    
    Graph G(n);for(int i =0, u, v; i < n -1; i++){
        cin >> u >> v;
        u--, v--;
        G[u].push_back(v);
        G[v].push_back(u);}
    
    LCA tree(G);
    queue<int> que;
    vector<int>dis(n, INF);for(int i =0, x; i < k; i++){
        cin >> x;
        x--;
        que.push(x);
        dis[x]=0;}while(que.size()){int u = que.front();
        que.pop();for(auto v: G[u])if(dis[v]== INF){
                dis[v]= dis[u]+1;
                que.push(v);}}auto dist =[&](int x,int y){returnmin(tree.dist(x, y), dis[x]+ dis[y]);};for(int i =0, u, v; i < q; i++){
        cin >> u >> v;
        u--, v--;
        cout <<dist(u, v)<< endl;}return0;}
标签: 算法 图论 c++

本文转载自: https://blog.csdn.net/sblsf/article/details/140877273
版权归原作者 pystraf 所有, 如有侵权,请联系我们删除。

“P10289 [GESP样题 八级] 小杨的旅游”的评论:

还没有评论