Agitation exam and Cheese Li pan

Little late to repair the road
road.in/.out/.cpp
【Problem Description】
Urban ⼩ later life is a small tree (tree refers to one containing n nodes and communicating FIG free edges to the n-1), numbered from 1 to n nodes, each edge has a weight value, represented by by this edge when you need to pay money (note that it is possible this value is negative, which means you go through this edge when you can make money) is a little late distinguished road work, he lived in node s, he can select an arbitrary node m, and the simple path from node s to node m (refer to the simple path does not pass through the same node twice) All weights are modified on the side of the now little later to obtain 0. q requests, each request is given as ab, showing little early late friends want a small simple path away from the node a to node B, a small late early hope to minimize the need to pay less money.
It should be noted that this request q little late obtained are independent, which means you only need to every request, decided a little late road program, the small early money required to pay as little as possible.
[Input Format]
Enter the file name road.in.
The first row of three positive integer n, q, s.
Next, n-1 lines, each line XYZ three integers, indicates there is an edge (x, y), value of z.
Next q rows, each of two integers ab & n, indicates a request.
[Output format]
Output file name road.out.
Q lines of two integer representing the least amount of money required to pay.
[Sample input]
3 2 1
1 2 1
2 3 1
1 2
1 3
[Sample output]
0
0
Sample [explain]
For the first query 12, may be small road repair later from 1 to 2 does not require such a small early
Payment of money;
13 for the second interrogation, from a small repair to be later than the passage 3, so that does not require small early
To pay the money.
[Agreement] and the size of data
For 30% of the data, n≤1000, q≤1000.
To 100% of the data, 1≤n, q≤200000,1≤x, y≤n, | z | ≤1000.
 
answer:
Maintaining the maximum cross-sectional LCA + tree. This problem no roots, s is the root for convenience, can be calculated for each point S to DIS, and then consider the situation is cleared, as the xy lca S, Y is lca, lca X is, below the xy lca S
For the first cleaning can select the left or right side clearance, for the second three kinds, the minimum clearance on the line, similar to the first and fourth, but the final result is subtracted again dis [lca (x, y) ] (minus twice the time of the examination, then 100> 0).
This is lca part, the rest of the tree will need to maintain maximum cross-section of dis, and then the bottom point of dis minus on the line
 
Code:
#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;
}

 

Guess you like

Origin www.cnblogs.com/sanjinliushi/p/11704800.html