http://codevs.cn/problem/3287/
题目描述
国有 座城市,编号从 到 ,城市之间有 条双向道路。每一条道路对车辆都有重
量限制,简称限重。现在有 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的
情况下,最多能运多重的货物。
输入格式
输入文件第一行有两个用一个空格隔开的整数 , 表示 国有 座城市和 条道
路。
接下来 行每行 个整数 ,每两个整数之间用一个空格隔开,表示从 号城市
到 号城市有一条限重为 的道路。注意: 不等于 ,两座城市之间可能有多条道路。
接下来一行有一个整数 ,表示有 辆货车需要运货。
接下来 行,每行两个整数 、 ,之间用一个空格隔开,表示一辆货车需要从 城市
运输货物到 城市,注意: 不等于 。
输出格式
输出共有 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货
车不能到达目的地,输出 。
输入样例
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3
输出样例
3
-1
3
数据范围
题解
可以证明最优路径一定在最大生成树(森林)上,于是题目便转化为,询问森林中两点路径上边权最小值,连通性用并查集判断即可。
对于一棵树上的一次询问,可以用倍增的方法解决。
表示点 向上 步到达的结点
表示点 向上 步的路径中的边权最小值
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #define N 10005 #define M 50005 #define depth 21 using namespace std; int n,m,q,cnt,tot,ans; int f[N],last[N],dep[N]; int anc[N][22],g[N][22]; struct hh {int to,next,w;}e[M<<1]; struct hhh {int l,r,w;}line[M<<1]; bool cmp(hhh a,hhh b){return a.w>b.w;} int read() { int ret=0;char c=getchar(); while(!isdigit(c))c=getchar(); while(isdigit(c)){ret=(ret<<1)+(ret<<3)+c-'0';c=getchar();} return ret; } void add(int a,int b,int w) { e[++tot].to=b; e[tot].next=last[a]; e[tot].w=w; last[a]=tot; } void bfs(int root) { int i,j,now; stack<int> s; s.push(root);dep[root]=1; for(i=0;i<depth;i++) anc[root][i]=root; while(!s.empty()) { now=s.top();s.pop(); if(now!=root) for(i=1;i<depth;i++) { anc[now][i]=anc[anc[now][i-1]][i-1]; g[now][i]=min(g[now][i-1],g[anc[now][i-1]][i-1]); } for(i=last[now];i;i=e[i].next) if(!dep[e[i].to]) { anc[e[i].to][0]=now; dep[e[i].to]=dep[now]+1; g[e[i].to][0]=e[i].w; s.push(e[i].to); } } } void swim(int& x,int h) { int i; for(i=0;h;i++) { if(h&1) x=anc[x][i]; h>>=1; } } int getlca(int x,int y) { int i,j; if(dep[x]<dep[y]) swap(x,y); swim(x,dep[x]-dep[y]); if(x==y) return x; while(true) { for(i=0;anc[x][i]!=anc[y][i];i++); if(!i) return anc[x][0]; x=anc[x][i-1];y=anc[y][i-1]; } } int query(int x,int y) { int i,ret=9999999,h; h=dep[y]-dep[x]; for(i=depth;i>=0;i--) if((1<<i)<=h) { h-=(1<<i); ret=min(ret,g[y][i]); y=anc[y][i]; } return ret; } int find(int x){return f[x]==x?x:f[x]=find(f[x]);} int main() { int i,j,u,v,w,fx,fy,lca; n=read();m=read(); for(i=1;i<=m;i++) line[i].l=read(),line[i].r=read(),line[i].w=read(); sort(line+1,line+1+m,cmp); for(i=1;i<=n;i++) f[i]=i; for(i=1;i<=m;i++) { u=line[i].l;v=line[i].r;w=line[i].w; fx=find(u);fy=find(v); if(fx!=fy) { f[fx]=fy;cnt++; add(u,v,w);add(v,u,w); if(cnt==n-1) break; } } for(i=1;i<=n;i++) for(j=0;j<depth;j++) g[i][j]=9999999; bfs(1); q=read(); for(i=1;i<=q;i++) { u=read();v=read(); if(find(u)!=find(v)){puts("-1");continue;} lca=getlca(u,v); ans=min(query(lca,u),query(lca,v)); printf("%d ",ans); } return 0; }