码迷,mamicode.com
首页 > 其他好文 > 详细

考试又?叒叕出锅了

时间:2019-10-19 20:31:12      阅读:68      评论:0      收藏:0      [点我收藏+]

标签:需要   getchar   int   最小   pac   har   最大值   +=   else   

小迟修马路
road.in/.out/.cpp
【问题描述】
?小迟生活的城市是1棵树(树指的是一个含有 n 个节点以及 n-1 条边的无向连通图),节点编号从 1 到 n,每条边拥有一个权值 value,表示通过这条边的时候你需要交纳的金钱(注意,有可能这个值为负数,也就是说你经过这条边的时候你可以赚钱)小迟是一个杰出的马路工,他居住在节点 s,他能够选择任意一个节点m,并将从节点 s 到节点 m 的简单路径(简单路径指的是不经过同一个节点两次)上的所有边的权值都修改为 0.现在小迟获得 q 个请求,每个请求都是以 a b 的形式给出,表示小迟的好朋友小早希望从节点 a 走简单路径到节点 b,小迟希望能最小化小早需要缴纳的钱。
需要注意的是,小迟获得的这 q 个请求是相互独立的,也就是说您只需要对于每一个请求,决定小迟的一个修路方案,使得小早需要缴纳的钱尽可能的少。
【输入格式】
输入文件名为 road.in。
第一行三个正整数为 n,q,s。
接下来 n-1 行,每行三个整数 x y z, 表示有一条边 (x,y),value 为 z。
接下来 q 行,每个两个正整数 a b,表示请求。
【输出格式】
输出文件名为 road.out。
Q 行,每行两个整数,表示需要缴纳的最少的钱。
【样例输入】
3 2 1
1 2 1
2 3 1
1 2
1 3
【样例输出】
0
0
【样例解释】
对于第一次询问 1 2, 小迟可以修从 1 到 2 的路,从而使得小早不需要
缴纳金钱;
对于第二次询问 1 3, 小迟可以修从 1 到 3 的路,从而使得小早不需要
缴纳金钱。
【数据规模及约定】
对于 30% 的数据,n≤1000,q≤1000.
对于 100% 的数据,1≤n,q≤200000,1≤x,y≤n,|z|≤1000.
 
题解:
LCA+树剖维护最大值。这题无根,为了方便以s为根,可以算出每个点到S的dis,然后考虑清零情况,S为x y的lca,y为lca,x为lca,x y的lca在S下方
对于第一种只能选择清左边或者清右边,对于第二三种,清到最小值就行,对于第四种与第一种类似,但是最后结果要再减去dis[lca(x,y)](考试的时候减了两倍,然后100->0)。
这是lca部分,剩下的就需要树剖维护dis中的最大值,再用底下点的dis减去就行
 
代码:
#include<iostream>
#include<cstdio>
#define lson k<<1,l,mid
#define rson k<<1|1,mid+1,r
#define ls k<<1
#define rs k<<1|1
#define mid ((l+r)>>1)
using namespace std;
const int N=200005,inf=2e9;
int n,m,cnt,s,mi,tot;
int head[N],fa[N][23],dis[N],dep[N];
int son[N],top[N],val[N],siz[N],id[N];
int tr[N<<2];
struct node{
    int to,nxt,dis;
}e[N<<1];
inline int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch<0||ch>9){if(ch==-)w=-1;ch=getchar();}
    while(ch>=0&&ch<=9){s=s*10+ch-0;ch=getchar();}
    return w*s;
}
inline void add(int from,int to,int dis){
    e[++cnt]=(node){to,head[from],dis};
    head[from]=cnt;
}
void dfs(int x,int f,int di){
    dep[x]=dep[f]+1;
    fa[x][0]=f;
    dis[x]=dis[f]+di;siz[x]=1;
    for(int i=1;(1<<i)<=dep[x];++i)
        fa[x][i]=fa[fa[x][i-1]][i-1];
    for(int i=head[x];i;i=e[i].nxt)
        if(e[i].to!=f){
            dfs(e[i].to,x,e[i].dis);
            siz[x]+=siz[e[i].to];
            if(siz[e[i].to]>siz[son[x]])son[x]=e[i].to;
        }
}
void dfs2(int x,int topf){
    top[x]=topf;id[x]=++tot;val[tot]=dis[x];
    if(!son[x])return ;
    dfs2(son[x],topf);
    int y;
    for(int i=head[x];i;i=e[i].nxt){
        y=e[i].to;
        if(y==fa[x][0]||y==son[x])continue;
        dfs2(y,y);
    }
}
inline int lca(int x,int y){
    if(dep[x]>dep[y])x^=y^=x^=y;
    for(int i=21;i>=0;i--)
        if(dep[x]<=dep[fa[y][i]])
            y=fa[y][i];
    if(x==y)return x;
    for(int i=21;i>=0;--i){
        if(fa[x][i]==fa[y][i])continue;
        x=fa[x][i];
        y=fa[y][i];
    }
    return fa[x][0];
}
inline void update(int k){
    tr[k]=max(tr[ls],tr[rs]);
}
void build(int k,int l,int r){
    if(l==r){
        tr[k]=val[l];
        return ;
    }
    build(lson);build(rson);
    update(k);
}
int ask(int k,int l,int r,int x,int y){
    if(l==x&&y==r){
        return tr[k];
    }
    if(y<=mid)return ask(lson,x,y);
    else if(x>mid)return ask(rson,x,y);
    else return max(ask(lson,x,mid),ask(rson,mid+1,y));
}
void query(int x,int y){
    mi=-inf;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        mi=max(ask(1,1,n,id[top[x]],id[x]),mi);
        x=fa[top[x]][0];
    }
    if(dep[x]>dep[y])swap(x,y);
    mi=max(ask(1,1,n,id[x],id[y]),mi);
}
int main(){
     freopen("road.in","r",stdin);
     freopen("road.out","w",stdout);
    n=read();m=read();s=read();
    int x,y,z;
    for(int i=1;i<n;++i){
        x=read();y=read();z=read();
        add(x,y,z);add(y,x,z);
    }
    dfs(s,0,0);
    dfs2(s,s);
    build(1,1,n);
    int ans;
    while(m--){
        x=read();y=read();
        z=lca(x,y);
        if(z==s){
            query(y,s);mi=dis[y]-mi;
            ans=dis[x]+(mi>0?0:mi);
            query(x,s);mi=dis[x]-mi;
            ans=min(ans,dis[y]+(mi>0?0:mi));
            printf("%d\n",ans);
        }
        else if(z==x){
            query(y,x);mi=dis[y]-mi;
            printf("%d\n",mi>0?0:mi);
        }
        else if(z==y){
            query(x,y);mi=dis[x]-mi;
            printf("%d\n",mi>0?0:mi);
        }
        else {
            query(y,z);mi=dis[y]-mi;
            ans=dis[x]+(mi>0?0:mi)-dis[z];
            query(x,z);mi=dis[x]-mi;
            ans=min(ans,dis[y]+(mi>0?0:mi)-dis[z]);
            printf("%d\n",ans);
        }
    }
    return 0;
}

 

考试又?叒叕出锅了

标签:需要   getchar   int   最小   pac   har   最大值   +=   else   

原文地址:https://www.cnblogs.com/sanjinliushi/p/11704800.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!