题目描述
A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。输入输出格式
输入格式: 输入文件名为 truck.in。
输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道
路。
接下来 m 行每行 3 个整数 x、 y、 z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。意:x 不等于 y,两座城市之间可能有多条道路。
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y。
输出文件名为 truck.out。
输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货
车不能到达目的地,输出-1。
输入输出样例
输入样例#1:4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3
输出样例#1:3
-1
3
说明
对于 30%的数据,0 < n < 1,000,0 < m < 10,000,0 < q< 1,000; 对于 60%的数据,0 < n < 1,000,0 < m < 50,000,0 < q< 1,000; 对于 100%的数据,0 < n < 10,000,0 < m < 50,000,0 < q< 30,000,0 ≤ z ≤ 100,000。
【思路】kruskal求最大生成树,发现加入一条边使x,y联通,则该条边的权值为所求。易证。
有一个巧妙的想法,因为边是由大到小加进来的,所以越往上的祖先所管的边权越小,因此我们只要跑一下最大生成树再跑lca便可求解。
<span style="font-size:18px;">#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn=100005;
struct data{
int u,v,w;
bool operator <(const data&b)const{
return(w>b.w);
}
}e[maxn];
int q,n,m,anc[maxn],fa[maxn],cnt=1,num,dep[maxn],f[maxn][19],val[maxn];
inline int get(){
char c;while(!isdigit(c=getchar()));
int p=c-48;while(isdigit(c=getchar()))p=p*10+c-48;
return p;
}
inline int lca(int a,int b){
if(dep[a]<dep[b])swap(a,b);
int j=0;
while((1<<(j+1))<=dep[a])++j;
for(int i=j;i>=0;--i){ //注意i可以取零
if((dep[a]-(1<<i))>=dep[b])a=f[a][i];
}
if(a==b)return a;
for(int i=j;i>=0;--i){
if(f[a][i] && f[a][i]!=f[b][i]){
a=f[a][i];
b=f[b][i];
}
}
return fa[a];
}
inline int Find(int x){
if(x==anc[x])return anc[x];
else return (anc[x]=Find(anc[x]));
}
int main(){
memset(f,0,sizeof(f));
memset(fa,0,sizeof(fa));
n=get();m=get();
for(int i=1;i<=m;++i)e[i].u=get(),e[i].v=get(),e[i].w=get();
sort(e+1,e+1+m);num=n;
for(int i=1;i<=n;++i)anc[i]=i;
for(int i=1;i<=m;++i){
int x=Find(anc[e[i].u]);
int y=Find(anc[e[i].v]);
if(x!=y){
anc[x]=anc[y]=fa[x]=fa[y]=++n; //想象一下
fa[n]=0,val[n]=e[i].w,anc[n]=n;
++cnt;if(cnt==num)break;
}
}
dep[n]=0;
for(int i=n-1;i;--i){
dep[i]=dep[fa[i]]+1;
f[i][0]=fa[i];
int j=1;
while(f[f[i][j-1]][j-1])f[i][j]=f[f[i][j-1]][j-1],++j;
}
q=get();
while(q--){
int x=get(),y=get();
if(Find(x)!=Find(y))printf("-1\n");
else printf("%d\n",val[lca(x,y)]);
}
return 0;
}</span>