UESTC - 92 Journey(LCA)1012四川省赛

题目链接:点击打开链接

题意:给你一棵n个结点的生成树,在任选两个点建立一条边,然后有q个询问,求加上这条边后两点的距离减少了多少,如果没有减少或者是增加了,那么输出0;

分析:既然是一棵树,那么我们就可以在树上进行操作,第一想法就是LCA,假设在u和v两点间建立的边,求x到y 的距离,原来的就是dis[x]+dis[y]-2*dis[lca(x,y)]

经过这条边的距离就是xu+uv+vy或者xv+uv+uy,取两者中最小的,然后和原来的距离做差就可以了。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <ctype.h>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#define eps 1e-8
#define INF 0x7fffffff
#define maxn 100005
#define PI acos(-1.0)
using namespace std;
typedef long long LL;
const int N = 100005;
int n , m , pre[N] , mcnt;
bool vis[N];
struct edge
{
    int x , next ,flag ;
} e[N << 1];

int dep[N] , f[18][N] , Lev , s[N],dis[N];///1<<16 < N, f[j][i] 表示i的第2^j个祖先
int shang[N],xia[N];

void dfs(int u ,int fa,int c,int d)///也可以用bfs,但bfs不能统计节点孩子个数
{
    dep[u] = d + 1;
    f[0][u] = fa ;
    dis[u]=c;
    for (int i = pre[u] ; ~i ; i = e[i].next)
    {
        int y = e[i].x;
        if(y==fa)
            continue;
        dfs(y,u,c+e[i].flag,d+1);
    }
}

int LCA(int x , int y)
{
    if (dep[x] > dep[y]) swap(x , y);
    for (int i = Lev ; i >= 0 ; -- i)///找y的第dep[y] - dep[x]个祖先
        if (dep[y] - dep[x] >> i & 1)
            y = f[i][y];
    if (x == y) return y;
    for (int i = Lev ; i >= 0 ; -- i)
        if (f[i][x] != f[i][y])
            x = f[i][x] , y = f[i][y];
    return f[0][x];
}

void init()
{
    memset(pre , -1 , sizeof(pre));
    memset(dis,0,sizeof dis);
    mcnt = 0;
}
void addedge(int x,int y ,int f)
{
    e[mcnt].x = y,
    e[mcnt].next = pre[x],
    e[mcnt].flag = f;
    pre[x] = mcnt ++;
}
void work(int n,int m)
{
    int i , j , x , y , z,anc;
    init();
    for (i = 1 ; i < n ; ++ i)
    {
        scanf("%d%d%d",&x,&y,&z);
        addedge(x,y,z);
        addedge(y,x,z);
    }
    dfs(1 ,-1, 0,0);
    for (j = 1 ; 1 << j < n ; ++ j)///ST算法求祖先
        for (i = 1 ; i <= n ; ++ i)
            f[j][i] = f[j - 1][f[j - 1][i]];
    Lev = j - 1;
    int u,v,l;
    scanf("%d%d%d",&u,&v,&l);
    while(m--)
    {
        scanf("%d%d",&x,&y);
        int xu,uv,vy,xv,uy,xy;
        xu=dis[x]+dis[u]-2*dis[LCA(x,u)];
        vy=dis[v]+dis[y]-2*dis[LCA(v,y)];
        xv=dis[x]+dis[v]-2*dis[LCA(x,v)];
        uy=dis[u]+dis[y]-2*dis[LCA(u,y)];
        xy=dis[x]+dis[y]-2*dis[LCA(x,y)];
        int d1,d2,d3;
        d1=xu+l+vy;
        d2=xv+l+uy;
        d3=min(d1,d2);
        int ans=max(0,(xy-d3));
        printf("%d\n",ans);
    }
}

int main()
{
    int t,cnt=1;
    cin>>t;
    while(t--)
    {
        printf("Case #%d:\n",cnt++);
       scanf("%d%d",&n,&m);
       work(n,m);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值