BZOJ1832 聚会

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

原文地址:https://www.cnblogs.com/Rorshach/p/8724875.html

时间: 2024-07-31 16:52:41

BZOJ1832 聚会的相关文章

BZOJ1832 [AHOI2008] 聚会

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1832 Description Y岛风景美丽宜人,气候温和,物产丰富.Y岛上有N个城市,有N-1条城市间的道路连接着它们.每一条道路都连接某两个城市.幸运的是,小可可通过这些道路可以走遍Y岛的所有城市.神奇的是,乘车经过每条道路所需要的费用都是一样的.小可可,小卡卡和小YY经常想聚会,每次聚会,他们都会选择一个城市,使得3个人到达这个城市的总费用最小. 由于他们计划中还会有很多次聚会,每次

【BZOJ1832】【AHOI2008】聚会 倍增lca

这道题写不了tarjanlca. 50W的询问,也就是150W次lca查询,每次加三条边,内存妥妥要爆. 只能退求logn的倍增lca了. sad story. 还好一遍AC. 题解: 就是发现每次询问三个点之间有唯一的路径集,那么我们选其中两个取lca,然后另一个点自己走到这个lca, 就可以贪心取得答案. 代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorit

bzoj-3170 3170: [Tjoi 2013]松鼠聚会(计算几何)

题目链接: 3170: [Tjoi 2013]松鼠聚会 Time Limit: 10 Sec  Memory Limit: 128 MB Description 有N个小松鼠,它们的家用一个点x,y表示,两个点的距离定义为:点(x,y)和它周围的8个点即上下左右四个点和对角的四个点,距离为1.现在N个松鼠要走到一个松鼠家去,求走过的最短距离. Input 第一行给出数字N,表示有多少只小松鼠.0<=N<=10^5下面N行,每行给出x,y表示其家的坐标.-10^9<=x,y<=10^

n年的一次聚会

今日聚会有a,b,b1,c,d 五人一起吃饭. 先谈谈各自的变化吧. a 毕业之后,他爸给他买了一个京a的牌照,然后出印度留学,然后回到北京,现在算一个中层领导,不过比较忙,刚刚聚餐完毕就立马回去加班干活了. b毕业之后一人来到北京,开始北漂,在校时还专门参加了日语培训.北漂了3年,找到一个北京媳妇.今年5月份结婚,就是场上b1 c毕业之后在成都待了3个月,然后开始北漂,北漂一年后在成都商贷买房,2年后结婚,现在已经怀孕,现在正琢磨着未来的孩子在北京上学,购买学区房等等. d毕业之后在成都待了3

树形动态规划 fjutoj-2392 聚会的快乐

聚会的快乐 TimeLimit:1000MS  MemoryLimit:128MB 64-bit integer IO format:%lld Problem Description 你要组织一个由你公司的人参加的聚会.你希望聚会非常愉快,尽可能多地找些有趣的热闹.但是劝你不要同时邀请某个人和他的上司,因为这可能带来争吵.给定N个人(姓名,他幽默的系数,以及他上司的名字),编程找到能使幽默系数和最大的若干个人. Input 第一行一个整数N(N<100).接下来有N行,每一行描述一个人的信息,信

聚会宁夏【之一】

聚会宁夏 2016年7月15-20日,北师大历史系65级同学,应边聪明.杨森翔之邀,在宁夏聚会.期间,游览了吴忠董府.板桥道堂.鸿乐府,两馆一中心.黄河楼.黄河坛.黄河大峡谷.百零八塔.沙坡头.金沙岛.西夏王陵.影视城.沙湖.中阿之轴等.

bzoj1037[ZJOI2008]生日聚会

bzoj1037[ZJOI2008]生日聚会 题意: 一排小孩坐着玩游戏.就座的方案满足如下条件:对于任意连续的一段,男孩与女孩的数目之差不超过k.给出男孩数,女孩数和k,求就座方案数除以12345678的余数. 题解: dp方程见程序,i1i2表示当前选了几男几女,i3i4分别表示当前男比女多几个和女比男多几个. 代码: 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define

2016同学聚会登记

南宵中学06届7班毕业十周年聚会,[时间]大年初三上午11点,[地点]龙田馨园酒店(龙光路99号),有空参加的同学来吱一声呀!O(∩_∩)O √数学祖云老师13015727608 语文回民老师13075989980 英语林素梅老师13559938192 姓名.住址,在家.空闲时间.联系方式 √薛挺,13110545105 郭明亮,初三才回来,鼓楼区买房,18396521165 √郭锡超,玉桂初二有空,18690883030 √谢瑞鸿,谢塘,初二有空,15806051921 √翁海燕,城坂,初六上

2017深圳发烧友聚会第十三届圆满结束

7月30日,由LittleDot和雷音音频承办的第13届深圳发烧友聚会在深圳大中华喜来登酒店举行. 本场活动以捐献书籍和教育设施为主,改善偏远农村小学教学器材匮乏窘境 .活动主题是以"乐以载道,献书助学"持续进行,为表谢意,深圳发烧友聚会主办方和所有协办方.赞助商决定提供献书发烧友抽取丰厚奖品的机会.深圳发烧友聚会诚邀了各位音乐发烧友.媒体和厂商朋友参加2017年度深圳发烧盛典·第13届深圳耳机发烧友聚会. 当天,合作媒体:广东广播电视台.耳机大家坛.乐享派.数字尾巴.半烧主义.知客数