题目描述
(A)国有(n)座城市,编号从(1)到(n),城市之间有(m)条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有
(q)辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
输入格式
第一行有两个用一个空格隔开的整数(n),(m)表示 (A) 国有(n)座城市和(m)条道路。
接下来(m)行每行3个整数(x),(y),(z)每两个整数之间用一个空格隔开,表示从(x)号城市到(y)号城市有一条限重为z的道路。注意:(x)不等于 (y),两座城市之间可能有多条道路。
接下来一行有一个整数 (q),表示有 $q $辆货车需要运货。
接下来 (q) 行,每行两个整数 (x)、(y),之间用一个空格隔开,表示一辆货车需要从 (x) 城市运输货物到(y)城市。
输出格式
共有(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,0000;)
代码
我们通过构造kruskal重构树,在树上查询两点lca的点权值,即为答案。
关于kruskal重构树操作
如将边权按降序排序
则LCA(u,v)的权值代表 原图 u到v路径上最大边权的最小值
如将边权按升序排序
则LCA(u,v)的权值代表 原图 u到v路径上最小边权的最大值
#include<bits/stdc++.h>
using namespace std;
const int maxn=200000+100,maxm=200000+100,md=20+5;
int head[maxn],val[maxn],f[maxn],dep[maxn],lg[maxn];
int ff[maxn][md];
int size=0,cnt=0;
struct tree
{
int to,next;
}e[maxm<<1];
struct edge
{
int u,v,val;
}E[maxm<<1];
int n,m;
void init()
{
for(int i=1;i<=n;i++)
f[i]=i;
}
int find(int x)
{
return f[x]==x?x:f[x]=find(f[x]);
}
void addedge(int u,int v)
{
e[++size].to=v;e[size].next=head[u];head[u]=size;
}
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
bool cmp(const edge&a,const edge&b)
{
return a.val>b.val;
}
void kruskal()
{
for(int i=1;i<=m;i++)
{
int u=E[i].u,v=E[i].v;
int fu=find(u),fv=find(v);
if(fu!=fv)
{
cnt++;
f[cnt]=f[fu]=f[fv]=cnt;
val[cnt]=E[i].val;
addedge(cnt,fu);addedge(fu,cnt);
addedge(fv,cnt);addedge(cnt,fv);
}
}
}
void dfs(int u,int fa)
{
dep[u]=dep[fa]+1;
ff[u][0]=fa;
for(int i=1;i<=lg[dep[u]];i++)
ff[u][i]=ff[ff[u][i-1]][i-1];
for(int i=head[u];i;i=e[i].next)
{
int to=e[i].to;
if(to==fa)continue;
dfs(to,u);
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y])
swap(x,y);
while(dep[x]>dep[y])
x=ff[x][lg[dep[x]-dep[y]]];
if(x==y)
return x;
for(int i=lg[dep[x]];i>=0;i--)
if(ff[x][i]!=ff[y][i])x=ff[x][i],y=ff[y][i];
return ff[x][0];
}
int main()
{
n=read(),m=read();cnt=n;
init();
for(int i=1;i<=m;i++)
E[i].u=read(),E[i].v=read(),E[i].val=read();
sort(E+1,E+1+m,cmp);
kruskal();
for(int i=1;i<=n;i++)
lg[i]=lg[i-1]+(1<<(lg[i-1]+1)==i);
for(int i=1;i<=cnt;i++)
if(!dep[i])
dfs(find(i),0);
int k=read();
for(int i=1;i<=k;i++)
{
int x=read(),y=read();
if(find(x)!=find(y))printf("-1
");
else printf("%d
",val[lca(x,y)]);
}
return 0;
}