Greedy Pirate Gym - 101810M (lca)

对于题意 如果想要获取的硬币数最多,也就是所走的路径和最大,再想一下就是除了t到s这条路外其他的路都是一定能做一遍的(ps 题目给的是一棵树)。

题目就可以理解为 给定2个点求之间的路径;

所有边长减去这两点路径就是答案;

维护一个根节点到其他点的路径长度 d

维护一个其他节点到根节点路径长度 d1;

给定s t;

所以 d1[s]+d[t]-d[lca(s,t)]-d1[lca(s,t)])即为2点之间的路径长度,

#include<cstdio>
#include<cctype>
#include<cstring>
#include<vector>
#include<algorithm>
#include<bits/stdc++.h>

#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define sc(x) scanf("%d",&(x))
#define inf 0x3f3f3f3f

using namespace std;

const int maxn=1e5+10;


struct edge{
    int u,v,w,w1,next;
}e[maxn*2];

int g[maxn*2],tot=0,d[maxn],d1[maxn];
int n,dep[maxn];

void make(int u,int v,int w,int w1)
{
    e[++tot]=(edge){u,v,w,w1,g[u]};
    g[u]=tot;
}


int fa[maxn],fathers[maxn][33];


void deep(int u,int v,int de,int dd,int td){
        fa[u]=v;
        fathers[u][0]=v;
        dep[u]=de;
        for(int i=g[u];i>0;i=e[i].next){
            if(e[i].v==v) continue;
            d1[e[i].v]=dd+e[i].w;
            d[e[i].v]=td+e[i].w1;
            deep(e[i].v,u,de+1,dd+e[i].w,td+e[i].w1);

        }
}

void ben(){
    int d=log(n)/log(2)+1;
    for(int k=1;k<=d;k++)
        for(int i=1;i<=n;i++)
        {
            fathers[i][k]=fathers[fathers[i][k-1]][k-1];
        }
}

int lca(int u,int v){
    int maxn=log(n)/log(2)+1;
    if(dep[u]<dep[v]) swap(u,v);
    int d=dep[u]-dep[v];
    for(int i=0;i<=maxn;i++)
        if((d>>i)&1) u=fathers[u][i];
    if(u==v) return u;
    for(int i=maxn;i>=0;i--)
    {
        if(fathers[u][i]!=fathers[v][i]){
            u=fathers[u][i];
            v=fathers[v][i];
        }
    }
    return fathers[u][0];
}

int main()
{
    int t,m;
    sc(t);
    while(t--)
    {
        tot=0;
        mem(g,0);
        sc(n);
        int ans=0;
        for(int i=1;i<n;i++)
        {
            int u,v,w,w1;
            sc(u),sc(v),sc(w),sc(w1);
            ans+=w+w1;
            make(u,v,w,w1);
            make(v,u,w1,w);
        }
        deep(1,-1,0,0,0);
        ben();
        sc(m);
        while(m--)
        {
            int s,t;
            sc(s),sc(t);
            int temp=lca(s,t);
            printf("%d\n",ans-(d1[s]+d[t]-d[temp]-d1[temp]));
        }
    }
    return 0;
}

 

posted @ 2019-07-30 15:38  Minun  阅读(154)  评论(0编辑  收藏  举报