• BZOJ1832 聚会


    Description:
    Y岛风景美丽宜人,气候温和,物产丰富。Y岛上有N个城市,有N-1条城市间的道路连接着它们。每一条道路都连接某两个城市。幸运的
    是,小可可通过这些道路可以走遍Y岛的所有城市。神奇的是,乘车经过每条道路所需要的费用都是一样的。小可可,小卡卡和小YY经常
    想聚会,每次聚会,他们都会选择一个城市,使得3个人到达这个城市的总费用最小。 由于他们计划中还会有很多次聚会,每次都选择一
    个地点是很烦人的事情,所以他们决定把这件事情交给你来完成。他们会提供给你地图以及若干次聚会前他们所处的位置,希望你为他们
    的每一次聚会选择一个合适的地点。
    Input:
    第一行两个正整数,NM。分别表示城市个数和聚会次数。后面有N-1行,每行用两个正整数AB表示编号为A和编号为B的城市之间有
    一条路。城市的编号是从1N的。再后面有M行,每行用三个正整数表示一次聚会的情况:小可可所在的城市编号,小卡卡所在的城市
    编号以及小YY所在的城市编号。
    Output:
    一共有M行,每行两个数PosCost,用一个空格隔开。表示第i次聚会的地点选择在编号为Pos的城市,总共的费用是经过Cost条道路所
    花费的费用。

    思路:思路很一眼,就是对每一组输入,有三种情况,A走到B和C的LCA出,B走到A和C的LCA处,C走到A和B的LCA处,不过细节小心,不要写挂

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 5e5 + 10;
     
    int head[N], now;
    struct edges{
        int to, next;
    }edge[N<<1];
    void add(int u,int v){ edge[++now] = {v, head[u]}; head[u] = now;}
     
    int n, m, fa[N][22], dep[N];
    void dfs(int x, int pre){
        fa[x][0] = pre;
        for(int i = head[x]; i; i = edge[i].next){
            int v = edge[i].to;
            if(v == pre) continue;
            dep[v] = dep[x] + 1;
            dfs(v, x);
        }
    }
    int LCA(int u,int v){
        if(dep[v] > dep[u]) swap(u, v);
        int k=dep[u]-dep[v];
        for(int i=0;i<=20;i++)
          if((1<<i)&k) u=fa[u][i];
        if(u == v) return u;
        for(int i = 20; i >= 0; i--)
          if(fa[u][i] != fa[v][i]) 
            u = fa[u][i], v = fa[v][i];
        return fa[u][0];
         
    }
    int main(){
        scanf("%d%d",&n, &m);
        int x, y, z;
        for(int i = 1; i < n; i++){
            scanf("%d%d",&x, &y);
            add(x, y); add(y, x);
        }
        dep[1] = 1; dfs(1, 1);  
        for(int j = 0; j <= 20; j++)
          for(int i = 1; i <= n; i++)
            fa[i][j + 1] = fa[fa[i][j]][j];
        for(int i = 1; i <= m; i++){
            scanf("%d%d%d",&x, &y, &z);
            int lca, pos, tmp, tot = 0, ans = 1e9;
             
            lca = LCA(x, y); tot += dep[x] + dep[y] - 2*dep[lca];
            tmp = LCA(lca, z); tot += dep[z] + dep[lca] - 2*dep[tmp];
            if(tot < ans) ans = tot, pos = lca;
             
            swap(x, z); tot = 0; 
            lca = LCA(x, y); tot += dep[x] + dep[y] - 2*dep[lca];
            tmp = LCA(lca, z); tot += dep[z] + dep[lca] - 2*dep[tmp];
            if(tot < ans) ans = tot, pos = lca;
             
            swap(y, z); tot = 0; 
            lca = LCA(x, y); tot += dep[x] + dep[y] - 2*dep[lca];
            tmp = LCA(lca, z); tot += dep[z] + dep[lca] - 2*dep[tmp];
            if(tot < ans) ans = tot, pos = lca;
             
            printf("%d %d
    ", pos, ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Android(java)学习笔记68:使用proguard混淆android代码
    SGU 194 Reactor Cooling
    关于流量有上下界的网络流问题的求解
    关于最小割的求解方法
    HDU 5311 Hidden String
    POJ 3548 Restoring the digits
    POJ 2062 HDU 1528 ZOJ 2223 Card Game Cheater
    ZOJ 1967 POJ 2570 Fiber Network
    HDU 1969 Pie
    HDU 1956 POJ 1637 Sightseeing tour
  • 原文地址:https://www.cnblogs.com/Rorshach/p/8724875.html
Copyright © 2020-2023  润新知