zoukankan      html  css  js  c++  java
  • 【洛谷 4281】紧急集合

    题目描述

    欢乐岛上有个非常好玩的游戏,叫做“紧急集合”。在岛上分散有N个等待点,有N-1条道路连接着它们,每一条道路都连接某两个等待点,且通过这些道路可以走遍所有的等待点,通过道路从一个点到另一个点要花费一个游戏币。

    参加游戏的人三人一组,开始的时候,所有人员均任意分散在各个等待点上(每个点同时允许多个人等待),每个人均带有足够多的游戏币(用于支付使用道路的花费)、地图(标明等待点之间道路连接的情况)以及对话机(用于和同组的成员联系)。当集合号吹响后,每组成员之间迅速联系,了解到自己组所有成员所在的等待点后,迅速在N个等待点中确定一个集结点,组内所有成员将在该集合点集合,集合所用花费最少的组将是游戏的赢家。

    小可可和他的朋友邀请你一起参加这个游戏,由你来选择集合点,聪明的你能够完成这个任务,帮助小可可赢得游戏吗?

    输入格式

    第一行两个正整数N和M(N<=500000,M<=500000),之间用一个空格隔开。分别表示等待点的个数(等待点也从1到N进行编号)和获奖所需要完成集合的次数。 随后有N-1行,每行用两个正整数A和B,之间用一个空格隔开,表示编号为A和编号为B的等待点之间有一条路。 接着还有M行,每行用三个正整数表示某次集合前小可可、小可可的朋友以及你所在等待点的编号。

    输出格式

    一共有M行,每行两个数P,C,用一个空格隔开。其中第i行表示第i次集合点选择在编号为P的等待点,集合总共的花费是C个游戏币。

    输入输出样例

    输入 #1
    6 4  
    1 2  
    2 3  
    2 4 
    4 5
    5 6
    4 5 6
    6 3 1
    2 4 4 
    6 6 6
    输出 #1
    5 2
    2 5
    4 1
    6 0
    
    
    

    说明/提示

    提示:

    40%的数据中N<=2000,M<=2000
    100%的数据中,N<=500000,M<=500000

     
    题解:罕见这么水的紫题。。。LCA直接上就行啦
    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    #include<bits/stdc++.h>
    using namespace std;
    const int N=500002;
    typedef long long ll;
    struct node{
        int next;
        int to;
    }e[N*2];
    int n,m,t,x,y,a,b,c,d[N],f[N][22];
    int cnt,head[N];
    void add(int x,int y){
        e[++cnt].to=y;
        e[cnt].next=head[x];
        head[x]=cnt;
    }
    void dfs(int u,int fa){
        d[u]=d[fa]+1;
        for(int i=0;i<=19;i++)
            f[u][i+1]=f[f[u][i]][i];
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(v==fa) continue;
            f[v][0]=u; dfs(v,u);
        }
    }
    int lca(int x,int y){
        if(d[x]<d[y]) swap(x,y);
        for(int i=20;i>=0;i--){
            if(d[f[x][i]]>=d[y]) x=f[x][i];
            if(x==y)  return x;
        }
        for(int i=20;i>=0;i--)
            if(f[x][i]!=f[y][i])
               { x=f[x][i]; y=f[y][i]; }
        return f[x][0];
    }
    int main(){
        freopen("4281.in","r",stdin);
        freopen("4281.out","w",stdout);
        scanf("%d %d",&n,&m);
        for(int i=1;i<n;i++){
            scanf("%d %d",&x,&y);
            add(x,y); add(y,x);
        }
        dfs(1,0);
        for(int i=1;i<=m;i++){
            ll ans=0;
            scanf("%d %d %d",&a,&b,&c);
            int t1=lca(a,b);                   
            int t2=lca(a,c);
            int t3=lca(b,c);
            if(t1==t2) t=t3;
            else if(t1==t3) t=t2;
            else if(t2==t3) t=t1;
            ans=d[a]+d[b]+d[c]-d[t1]-d[t2]-d[t3];     
            printf("%d %lld
    ",t,ans);
        }
        return 0;
    }
  • 相关阅读:
    各种数字证书区别
    微信支付前端对接流程
    ts笔记 流动类型
    支付宝支付前端对接流程
    ts笔记索引签名
    [翻译]Selenium API 命令和操作(JAVA)
    玩一玩yolo目标检测
    快速上手MyBatis
    Swift快速入门
    Windows远程桌面后不能粘贴问题处理
  • 原文地址:https://www.cnblogs.com/wuhu-JJJ/p/11840681.html
Copyright © 2011-2022 走看看