[HackerRank 101 Hack 51] Train Trip

来源:互联网 发布:心动网络工资 编辑:程序博客网 时间:2024/05/15 05:53

题意

给定一棵无根树,三个人在一些点上。对于一条边,如果一个人通过代价为A,两个人同时通过代价为B,三个人同时通过代价为C。求三个人最后到达点1的最小代价。可以重复通过某点。

题解

三个人到达点1,要么三个人各自走到1,要么三个人会和在某一点后再走到1。会和时要么三个人各自走,要么某两人先会和,再一起走到会和点与第三个人会和,再一起走到1。反正总共也就几个点,倍增求LCA,然后暴力枚举方案。

代码

/// by ztx/// blog.csdn.net/hzoi_ztx#include <bits/stdc++.h>#define Rep(i,l,r) for(i=(l);i<=(r);i++)#define rep(i,l,r) for(i=(l);i< (r);i++)#define Rev(i,r,l) for(i=(r);i>=(l);i--)#define rev(i,r,l) for(i=(r);i> (l);i--)#define Each(i,v)  for(i=v.begin();i!=v.end();i++)#define r(x)   read(x)typedef long long ll ;typedef double lf ;int CH , NEG ;template <typename TP>inline void read(TP& ret) {    ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;    if (CH == '-') NEG = true , CH = getchar() ;    while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;    if (NEG) ret = -ret ;}#define  kN  100010LL#define  infi 0x3f3f3f3f3f3f3f3fLLtemplate<typename TP>inline bool MI(TP&a,const TP&b){return a>b?a=b,true:false;}int n, v1, v2, v3;ll A, B, C, ans;int ps[10],tot;std::vector<int> g[kN];int sz[kN];int fa[18][kN], dep[kN];inline void dfs(int u,int fa=0) {    ::fa[0][u] = fa;    dep[u] = dep[fa]+1;    for (int k=1;k<18;k++) if (::fa[k-1][u]) ::fa[k][u]=::fa[k-1][::fa[k-1][u]];    if (u==v1) sz[u]++;    if (u==v2) sz[u]++;    if (u==v3) sz[u]++;    bool rec=false;    if (sz[u]>0 || u==1) ps[++tot]=u,rec=true;    for (int i=g[u].size()-1;i>=0;i--) if (g[u][i]!=fa) {        dfs(g[u][i],u);        if (sz[g[u][i]]) {            if (!rec && sz[u]>0) ps[++tot]=u,rec=true;            sz[u] += sz[g[u][i]];        }    }}inline int LCA(int u,int v) {    if (u == v) return u;    if (dep[u]<dep[v])u^=v^=u^=v;    for(int k=17;k>=0;k--) if(dep[fa[k][u]]>=dep[v]) u=fa[k][u];    if (u == v) return u;    for(int k=17;k>=0;k--) if(fa[k][u]!=fa[k][v]) u=fa[k][u],v=fa[k][v];    return fa[0][u];}inline int getlen(int u,int v) {    if (u == v) return 0;    if (dep[u]<dep[v])u^=v^=u^=v;    int ret=0;    for(int k=17;k>=0;k--) if(dep[fa[k][u]]>=dep[v]) ret+=(1<<k), u=fa[k][u];    if (u == v) return ret;    for(int k=17;k>=0;k--) if(fa[k][u]!=fa[k][v]) ret+=(1<<k+1),u=fa[k][u],v=fa[k][v];    return ret+2;}inline ll getreallen(int a,int b,int c) {    int lca = LCA(a,b);    int llca = LCA(lca,c);    ll now = A*getlen(a,b)+B*getlen(lca,c);    if (dep[llca] < dep[lca]) {        return now;    } else {        int lca1 = LCA(a,c);        int lca2 = LCA(b,c);        MI(now,A*getlen(a,b)+B*getlen(lca1,c));        MI(now,A*getlen(a,b)+B*getlen(lca2,c));        return now;    }}inline void calc() {    ans = infi;    for(int i=1;i<=tot;i++) {        MI(ans,A*(getlen(v1,ps[i])+getlen(v2,ps[i])+getlen(v3,ps[i]))+C*getlen(1,ps[i]));        MI(ans,getreallen(v1,v2,ps[i])+A*getlen(v3,ps[i])+C*getlen(1,ps[i]));        MI(ans,getreallen(v2,v3,ps[i])+A*getlen(v1,ps[i])+C*getlen(1,ps[i]));        MI(ans,getreallen(v1,v3,ps[i])+A*getlen(v2,ps[i])+C*getlen(1,ps[i]));    }}inline void work() {    memset(fa,0,sizeof fa);    int i, u, v;    Rep (i,1,n) g[i].clear(), sz[i]=0;    tot = 0;    r(n), r(A), r(B), r(C), r(v1), r(v2), r(v3);    rep(i,1,n) r(u), r(v), g[u].push_back(v),g[v].push_back(u);    dfs(1);    calc();    printf("%lld\n", ans);}int main() {    int T;    r(T);    while (T --> 0) work();    END: getchar(), getchar();    return 0;}
原创粉丝点击