Min Max Roads(树剖+线段树)
来源:互联网 发布:虚拟光驱软件免费版 编辑:程序博客网 时间:2024/06/06 12:26
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
题意:有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;}
- Min Max Roads(树剖+线段树)
- Min Max Roads Lightoj 1162
- [树链剖分] LightOJ 1162 - Min Max Roads
- LightOJ 1162 Min Max Roads(LCA倍增法或树链剖分)
- 士兵杀敌(三)用线段树做,注意max,min的求解
- [HDU] 5306 Gorgeous Sequence [区间取min&求和&求max][线段树]
- Min/max:
- Min-Max
- max min
- max min
- POJ 1785 Binary Search Heap Construction 【笛卡尔树构造,线段树RMQ(Range Max/Min Query)】
- Min-Min算法和Max-Min算法
- Min-Min算法和Max-Min算法
- Min-Min算法 Max-Min算法
- Min-Min算法和Max-Min算法
- Min-Min算法 Max-Min算法
- 【codechef】Ancient Berland Roads(线段树)
- Max Min的使用
- nginx+tomcat+memcache----3 memcache
- UVA, 10336 Rank the Languages
- [LeetCode]--8. String to Integer (atoi)
- 计算 TPS,QPS
- 第一期资料
- Min Max Roads(树剖+线段树)
- C# Winform控件贴透明png图片遇到的问题
- Apache mina2 用户指南(十四)状态机
- C语言(10)------逻辑运算符
- Java Output Formatting
- XMLHttpRequest的下一代fetch
- 学习FFmpeg API – 解码视频
- 任意字节对齐的内存分配和释放
- HDU:2571 命运(DP)