Min Max Roads(树剖+线段树)

来源:互联网 发布:虚拟光驱软件免费版 编辑:程序博客网 时间:2024/06/06 12:26

C - Min Max Roads
Time Limit:3000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu
Submit Status

Description

You live in a Big country where there are many bi-directional roads connecting the cities. Since the people of the country are quite intelligent, they designed the country such that there is exactly one path to go from one city to another. A path consists of one or more connected roads.

Here cities are denoted by integers and each road has a cost of traveling. Now you are given the information about the Country. And you are given some queries, each consists of two cities. You have to find the shortest and longest road in the path from one city to another.

Input

Input starts with an integer T (≤ 5), denoting the number of test cases.

The first line of each case is a blank line. The next line contains n (2 ≤ n ≤ 105) denoting the number of cities. Then there will be n-1 lines containing three integers each. They will be given in the form u v w (1 ≤ u, v ≤ n, 0 < w ≤ 105, u ≠ v) meaning that there is a road between u and v and the cost of the road is w.

The next line contains an integer q (1 ≤ q ≤ 25000) denoting the number of queries. Each of the next q lines contains two integers x and y (1 ≤ x, y ≤ n, x ≠ y).

Output

For each case, print the case number in a single line. Then for each query x y, you should print one line containing the shortest and longest road along the path. See the samples for formatting.

Sample Input

2

 

6

3 6 50

2 5 30

2 4 300

1 2 100

1 3 200

4

1 4

4 6

2 5

3 5

 

2

1 2 100

1

1 2

Sample Output

Case 1:

100 300

50 300

30 30

30 200

Case 2:

100 100

传送门:http://bak.vjudge.net/contest/133238#overview

题意:有n个点和n-1条边构成一个树,每条边有u,v,c,u和v代表该边相连的2个点,c是这条边的权值,进行m次询问:u,v,从u到v的路径中输出边权的最小值和最大值

题解:树链剖分模板题,边权

#include<cstdio>#include<algorithm>#include<string.h>#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1using namespace std;const int INF = 0x3f3f3f3f;const int maxn = 2e5 + 5;struct Edge{    int v,c,nxt;}edge[maxn*2];int top[maxn];//top[v]表示v所在的重链的顶端节点int f[maxn]; //父亲节点int deep[maxn];//深度int num[maxn];//num[v]表示以v为根的子树的节点数int p[maxn];//p[v]表示v与其父亲节点的连边在线段树中的位置int fp[maxn];//和p数组相反int son[maxn];//重儿子int d[maxn],head[maxn],Min[maxn<<2],Max[maxn<<2],tot,totp;void add(int u,int v,int c){    edge[tot].v=v;    edge[tot].c=c;    edge[tot].nxt=head[u];    head[u]=tot++;}int dfs1(int u,int fa,int cnt){    f[u]=fa;    deep[u]=cnt;    num[u]=1;    son[u]=0;    int mx=0,tmp;    for(int i=head[u];~i;i=edge[i].nxt){        int v=edge[i].v;        if(v==fa) continue;        tmp=dfs1(v,u,cnt+1);        if(tmp>mx) mx=tmp,son[u]=v;        num[u]+=tmp;    }    return num[u];}void dfs2(int u,int t){    top[u]=t;   // printf("[%d %d]\n",u,totp);    p[u]=totp++;    fp[p[u]]=u;    if(son[u]) dfs2(son[u],t);    else return;    for(int i=head[u];~i;i=edge[i].nxt){        int v=edge[i].v;        if(v==f[u]) continue;        if(v==son[u]){            d[p[v]]=edge[i].c;            continue;        }        dfs2(v,v);        d[p[v]]=edge[i].c;    }}void PushUP(int rt){    Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);    Min[rt]=min(Min[rt<<1],Min[rt<<1|1]);}void build(int l,int r,int rt){    if(l==r) {Min[rt]=Max[rt]=d[l];return;}    int m=(l+r)>>1;    build(lson);    build(rson);    PushUP(rt);}int query1(int L,int R,int l,int r,int rt){    if(L<=l&&R>=r) return Min[rt];    int m=(l+r)>>1;    int ret=INF;    if(L<=m) ret=min(ret,query1(L,R,lson));    if(R>m) ret=min(ret,query1(L,R,rson));    return ret;}int query2(int L,int R,int l,int r,int rt){    if(L<=l&&R>=r) return Max[rt];    int m=(l+r)>>1;    int ret=-INF;    if(L<=m) ret=max(ret,query2(L,R,lson));    if(R>m) ret=max(ret,query2(L,R,rson));    return ret;}void solve(int u,int v,int n){    int f1=top[u],f2=top[v],ans1=INF,ans2=-INF;    while(f1!=f2){       // printf("%d %d\n",f1,f2);        if(deep[f1]<deep[f2]){            swap(f1,f2);            swap(u,v);        }        ans1=min(ans1,query1(p[f1],p[u],1,n-1,1));        ans2=max(ans2,query2(p[f1],p[u],1,n-1,1));        u=f[f1];f1=top[u];    }    if(u!=v) {        if(deep[u]>deep[v]) swap(u,v);        ans1=min(ans1,query1(p[son[u]],p[v],1,n-1,1));        ans2=max(ans2,query2(p[son[u]],p[v],1,n-1,1));    }    printf("%d %d\n",ans1,ans2);}void print(int l,int r,int rt){    if(l==r){        printf("%d%c",Min[rt],l==totp-1?'\n':' ');        return;    }    int m=(l+r)>>1;    print(lson);    print(rson);}int main(){   // freopen("in.txt","r",stdin);    int T,n,m;    scanf("%d",&T);    for(int cas=1;cas<=T;cas++){        tot=0;        totp=0;        memset(head,-1,sizeof(head));        printf("Case %d:\n",cas);        scanf("%d",&n);        for(int i=0;i<n-1;i++){            int u,v,c;            scanf("%d%d%d",&u,&v,&c);            add(u,v,c);            add(v,u,c);        }        dfs1(1,0,1);        dfs2(1,1);        build(1,totp-1,1);       // print(1,totp-1,1);        scanf("%d",&m);        while(m--){            int u,v;            scanf("%d%d",&u,&v);            solve(u,v,totp);        }    }    return 0;}



0 0