北方大学 ACM 多校训练赛 第七场 C Castle(LCA)

【题意】给你N个点,N条不同的边,Q次询问,求出u,v之间的最短路。

【分析】题意很简单,就是求最短路,但是Q次啊,暴力DIJ?当然不行,观察到这个题边的数目和点的数目是相同的,也就是说这个图是由一棵树加了一条边而形成的。而对于一棵树,如果有Q次询问最短路,那就可以用LCA来做,复杂度QlogN,但是现在加了一条边,可能会使有些点之间的路径变短。假设多加的这条边的两个端点是U,V,那么对于询问的X,Y,有这么三种情况,直接过LCA,或者经过U,V,详情见代码。

#include <bits/stdc++.h>
#define met(a,b) memset(a,b,sizeof a)
#define pb push_back
#define mp make_pair
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lowbit(x) (x&(-x))
using namespace std;
typedef long long ll;
ll mod = 1e9+7;
const int N=3e4+50;
const int M=N*N+10;
int n,m,k,root,son,dis[N],dep[N],fa[N][20],parent[N];
int d;
vector<pair<int,int> >edg[N];
int Find(int x){
    if(parent[x]!=x)parent[x]=Find(parent[x]);
    return parent[x];
}
void Union(int x,int y){
    x=Find(x);
    y=Find(y);
    if(x==y)return;
    parent[y]=x;
}
void dfs(int u,int f){
    fa[u][0]=f;
    for(int i=1; i<20; i++){
        fa[u][i]=fa[fa[u][i-1]][i-1];
    }
    for(int i=0; i<edg[u].size(); i++){
        int v=edg[u][i].first;
        if(v==f)continue;
        dis[v]=dis[u]+edg[u][i].second;
        dep[v]=dep[u]+1;
        dfs(v,u);
    }
}
int Lca(int u,int v){
    int U=u,V=v;
    if(dep[u]<dep[v])swap(u,v);
    for(int i=19; i>=0; i--){
        if(dep[fa[u][i]]>=dep[v]){
            u=fa[u][i];
        }
    }
    if(u==v)return u;
    for(int i=19; i>=0; i--){
        if(fa[u][i]!=fa[v][i]){
            u=fa[u][i];
            v=fa[v][i];
        }
    }
    return fa[u][0];
}
int main(){
    int u,v,w;
    int T;
    scanf("%d",&T);
    while(T--){
        for(int i=0; i<N; i++)dis[i]=dep[i]=0,edg[i].clear(),parent[i]=i;
        met(fa,-1);
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++){
            scanf("%d%d%d",&u,&v,&w);
            u++;v++;
            if(Find(u)==Find(v))root=u,son=v,d=w;
            else{
                Union(u,v);
                edg[u].pb(mp(v,w));
                edg[v].pb(mp(u,w));
            }
        }
        dep[root]=1;
        dfs(root,-1);
        while(m--){
            scanf("%d%d",&u,&v);
            u++;v++;
            int lca=Lca(u,v);
            int ans1=dis[u]+dis[v]-2*dis[lca];
            int ans2=dis[u]+dis[son]-2*dis[Lca(u,son)]+dis[v]+dis[root]-2*dis[Lca(root,v)]+d;
            int ans3=dis[v]+dis[son]-2*dis[Lca(v,son)]+dis[u]+dis[root]-2*dis[Lca(root,u)]+d;
            printf("%d\n",min(ans1,min(ans2,ans3)));
        }
    }
    return 0;
}
时间: 2024-11-10 07:52:41

北方大学 ACM 多校训练赛 第七场 C Castle(LCA)的相关文章

HDU 4941 Magical Forest(map映射+二分查找)杭电多校训练赛第七场1007

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4941 解题报告:给你一个n*m的矩阵,矩阵的一些方格中有水果,每个水果有一个能量值,现在有三种操作,第一种是行交换操作,就是把矩阵的两行进行交换,另一种是列交换操作,注意两种操作都要求行或列至少要有一个水果,第三种操作是查找,询问第A行B列的水果的能量值,如果查询的位置没有水果,则输出0. 因为n和m都很大,达到了2*10^9,但水果最多一共只有10^5个,我的做法是直接用结构体存了之后排序,然后m

HDU 4902 Nice boat 2014杭电多校训练赛第四场F题(线段树区间更新)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902 解题报告:输入一个序列,然后有q次操作,操作有两种,第一种是把区间 (l,r) 变成x,第二种是把区间 (l,r) 中大于x的数跟 x 做gcd操作. 线段树区间更新的题目,每个节点保存一个最大和最小值,当该节点的最大值和最小值相等的时候表示这个区间所有的数字都是相同的,可以直接对这个区间进行1或2操作, 进行1操作时,当还没有到达要操作的区间但已经出现了节点的最大值跟最小值相等的情况时,说明

HDU 5371 (2015多校联合训练赛第七场1003)Hotaru&#39;s problem(manacher+二分/枚举)

HDU 5371 题意: 定义一个序列为N序列:这个序列按分作三部分,第一部分与第三部分相同,第一部分与第二部分对称. 现在给你一个长为n(n<10^5)的序列,求出该序列中N序列的最大长度. 思路: 来自官方题解:修正了一些题解错别字(误 先用求回文串的Manacher算法,求出以第i个点为中心的回文串长度,记录到数组p中 要满足题目所要求的内容,需要使得两个相邻的回文串,共享中间的一部分,也就是说,左边的回文串长度的一半,要大于等于共享部分的长度,右边回文串也是一样. 因为我们已经记录下来以

HDU 5371 (2015多校联合训练赛第七场1003)Hotaru&amp;#39;s problem(manacher+二分/枚举)

pid=5371">HDU 5371 题意: 定义一个序列为N序列:这个序列按分作三部分,第一部分与第三部分同样,第一部分与第二部分对称. 如今给你一个长为n(n<10^5)的序列,求出该序列中N序列的最大长度. 思路: 来自官方题解:修正了一些题解错别字(误 先用求回文串的Manacher算法.求出以第i个点为中心的回文串长度.记录到数组p中 要满足题目所要求的内容.须要使得两个相邻的回文串,共享中间的一部分,也就是说.左边的回文串长度的一半,要大于等于共享部分的长度,右边回文串也

UPC2018组队训练赛第七场

题目来自ICPC 2017 Japan Tsukuba A题:Secret of Chocolate Poles 有三种巧克力,分别是厚度为1的白色巧克力,厚度为1或者k的黑色巧克力.要求把巧克力放到高度为 l 的盒子里,并且要黑白相间,底部和顶部必须都是黑色的 当l=1,ans=1:当l<k,ans=(l-1)/2+1:当l=k,ans=(l-1)/2+2;当l>k时,就可以转化成排列组合问题了,枚举厚度为k的黑色巧克力数目i,然后对于每一种情况,再枚举厚度为1的黑色巧克力的数目j,那么此时

2018年第四阶段组队训练赛第七场

A: Secret of Chocolate Poles 题目描述 Wendy, the master of a chocolate shop, is thinking of displaying poles of chocolate disks in the showcase. She can use three kinds of chocolate disks: white thin disks, dark thin disks, and dark thick disks. The thin

Contest1814 - 2019年我能变强组队训练赛第七场

Scores of Final Examination On-Screen Keyboard Tally Counters Balance Scale #pragma GCC optimize(3,"Ofast","inline") #include <bits/stdc++.h> using namespace std; typedef long long ll; unordered_map<ll,bool> m1; int n,m,cnt

HDU 4864 Task (贪心+STL多集(二分)+邻接表存储)(杭电多校训练赛第一场1004)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4864 解题报告:有n台机器用来完成m个任务,每个任务有一个难度值和一个需要完成的时间,每台机器有一个可以工作的最长时间和一个可以完成的任务的难度的最大值, 一台机器能完成一个任务的条件是这台机器的最长工作时间和能完成任务的难度值必须都大于等于这个任务,而且一台机器最多完成一个任务,假设一个任务的时间为t,难度值为x,那么完成这个任务可以赚到的钱 money = 500 * t + 2 * x; 现在

HDU-4930 Fighting the Landlords 多校训练赛斗地主

只需要判断一个回合就可以了,枚举判断可以一次出完所有牌或者大过对面的牌的可能,注意的是4张相同的牌带两张牌的话是可以被炸弹炸的. #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <queue> #include <algorithm> #include <cstdlib> #include <ioma