P1967 货车运输
题目描述
\(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\n");
else printf("%d\n",val[lca(x,y)]);
}
return 0;
}