您的位置:首页 > 其它

【LCA&倍增】货物运输 @upcexam5909

2018-03-21 11:55 183 查看
时间限制: 1 Sec 内存限制: 128 MB

题目描述

在一片苍茫的大海上,有n座岛屿,岛屿与岛屿之间由桥梁连接,所有的岛屿刚好被桥梁连接成一个树形结构,即共n-1架桥梁,且从任何一座岛屿出发都能到达其他任何一座岛屿。

第i座桥梁有一个承重量wi,表示该桥梁一次性最多通过重量为wi的货物。

现在有m个货物运输路线,第i个路线要从岛屿xi出发到达岛屿yi。为了最大化利益,你需要求出在不超过路线上任何一架桥梁的承重量的基础上,每个路线最多运输重量为多少货物。

输入

第一行为两个整数n,m。

接下来n-1行,每行三个整数x,y,w,表示有一座承重量为w的桥梁连接岛屿x和y。

接下来m行,每行两个整数x,y,表示有一条从岛屿x出发到达岛屿y的路线,保证x≠y。

输出

输出共m行,每行一个整数,第i个整数表示第i条路线的最大重量。

样例输入

6 5

1 2 2

2 3 5

2 4 2

2 5 3

5 6 1

2 4

6 2

1 3

3 5

1 6

样例输出

2

1

2

3

1

提示

岛屿间连接情况如图所示:

2,4间只有一架桥,该路线最大运输重量为2

6,2间有两架桥,承重分别为3和1,该路线最大运输重量为1

剩余询问不再作解释

对于50%的数据n,m<=2000

对于100%的数据 n,m<=100000,w<=10^9

来源

2018山东冬令营

http://exam.upc.edu.cn/problem.php?id=5909

思路

第一次写倍增求LCA

这一题每次查询的两个点 x,y

可以考虑倍增求这两个点的LCA

用g[i][j]表示从i到i的第2^j个祖先的所经过的路的最小权值

维护时 g[i][j]=min( g[i][j-1] , g[ f[i][j-1] ][j-1] )

当x或y向根节点移动时,将对应路径上的最小值与答案取min

代码

#define FILE() freopen("../../in.txt","r",stdin)
#include <bits/stdc++.h>

using namespace std;
const int maxn = 100005;
const int maxl = 20;
const int INF = 0x3f3f3f3f;
int anc[maxn][maxl],fa[maxn],deep[maxn],n,m,cnt,head[maxn];//anc记录祖先,fa记录父亲节点,deep记录深度
int g[maxn][maxl];

struct edge{
int v,w,nex;
}ed[maxn*2];

void addedge(int u,int v,int w){
cnt++;
ed[cnt].v = v;
ed[cnt].w = w;
ed[cnt].nex = head[u];
head[u] = cnt;
}

void dfs(int x){
anc[x][0] = fa[x];
for(int i=1;i<maxl;i++){
anc[x][i] = anc[anc[x][i-1]][i-1];
g[x][i] = min(g[x][i-1],g[anc[x][i-1]][i-1]); //
a491
}
for(int i=head[x];i;i=ed[i].nex){
if(ed[i].v!=fa[x]){
int y = ed[i].v;
fa[y] = x;
deep[y] = deep[x]+1;
g[y][0] = ed[i].w; //
dfs(y);
}
}
}

int lca(int x,int y){
int ret = INF;
if(deep[x]<deep[y])swap(x,y);
for(int i=maxl-1;i>=0;i--){
if(deep[y]<=deep[anc[x][i]]){
ret = min(ret,g[x][i]);
x = anc[x][i];
}
}
//    if(x==y)return x;
for(int i=maxl-1;i>=0;i--){
if(anc[x][i]!=anc[y][i]){
ret = min(ret,g[x][i]);
ret = min(ret,g[y][i]);
x = anc[x][i];
y = anc[y][i];
}
}
if(x!=y){
ret = min(ret,g[x][0]);
ret = min(ret,g[y][0]);
}
return ret;
}

int main() {
//    FILE();
cin>>n>>m;
for(int i=0;i<n-1;i++){
int from,to,value;
scanf("%d%d%d",&from,&to,&value);
addedge(from,to,value);
addedge(to,from,value);
}
for(int i=0;i<n;i++){
for(int j=0;j<maxl;j++){
g[i][j] = INF;
}
}
dfs(1);
for(int i=0;i<m;i++){
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",lca(x,y));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: