描述
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 城市,注意:x 不等于 y。
输出格式
输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-1。
限制
每个测试点1s。
提示
对于 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。
题解
首先最大生成树能保证每两个城市之间的最优路径(贪心)。
然后就是找两个点的最近公共祖先,然后找两点之间的最小值,倍增顺便记个dp值即可。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int n,m,ct;
struct bian {int frm,to,v;} e[50002];
int fa[10002],zz,head[10002];
struct shu {int to,nx,v;} e2[100002];
int done[10002],g[10002][15];
int f[10002][15],h[10002];//2^14>16000
//------------------------------------------------------
void insert(int x,int y,int z)
{ct++; e[ct].frm=x; e[ct].to=y; e[ct].v=z;}
bool kp(const bian &i,const bian &j) {return i.v>j.v;}
void init()
{
scanf("%d%d",&n,&m);
int i,x,y,z;
for(i=1;i<=n;i++) fa[i]=i;
for(i=1;i<=m;i++)
{scanf("%d%d%d",&x,&y,&z);
insert(x,y,z);
}
sort(e+1,e+ct+1,kp);
}
void reinit(int x,int y,int z)
{
zz++; e2[zz].to=y; e2[zz].v=z; e2[zz].nx=head[x]; head[x]=zz;
zz++; e2[zz].to=x; e2[zz].v=z; e2[zz].nx=head[y]; head[y]=zz;
}
int find(int x)
{
if(fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
}
void klskl()
{
int i,r1,r2;
for(i=1;i<=ct;i++)
{r1=find(e[i].to); r2=find(e[i].frm);
if(r1!=r2)
{fa[r1]=r2;
reinit(e[i].frm,e[i].to,e[i].v);
}
}
}
//------------------------------------------------------------------------------
void dfs(int x)
{
done[x]=1;
int i,p;
for(i=1;i<14;i++)
{if(h[x]<(1<<i)) break;
f[x][i]=f[f[x][i-1]][i-1];
g[x][i]=min(g[x][i-1],g[f[x][i-1]][i-1]);
}
for(i=head[x];i;i=e2[i].nx)
{p=e2[i].to;
if(done[p]) continue;
h[p]=h[x]+1; f[p][0]=x; g[p][0]=e2[i].v;
dfs(p);
}
}
void lca(int x,int y)
{
if(h[x]<h[y]) swap(x,y);
int i,t,ans=1<<30;
t=h[x]-h[y];
for(i=13;i>=0;i--)
{if(t&(1<<i))
{ans=min(ans,g[x][i]); x=f[x][i];}
}
for(i=13;i>=0;i--)
{if(f[x][i]!=f[y][i])
{ans=min(ans,g[x][i]); ans=min(ans,g[y][i]);
x=f[x][i]; y=f[y][i];
}
}
if(x==y) printf("%d\n",ans);
else
{ans=min(ans,g[x][0]); ans=min(ans,g[y][0]);
printf("%d\n",ans);
}
}
void work()
{
int i,T,x,y,r1,r2,t;
memset(g,127,sizeof(g));
for(i=1;i<=n;i++)
{if(!done[i]) dfs(i);}
scanf("%d",&T);
while(T--)
{scanf("%d%d",&x,&y);
r1=find(x); r2=find(y);
if(r1!=r2) printf("-1\n");
else lca(x,y);
}
}
int main()
{
init(); klskl();
work();
return 0;
}