Description
A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
Input
第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道路。
接下来 m 行每行 3 个整数 x、y、z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意:x 不等于 y,两座城市之间可能有多条道路。
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y。
Output
输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-1。
Sample Input
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3
Sample Output
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。
题目分析:
今天自己讲完LCA后对LCA有了较深的理解 所以就找题来做啦
想要货车要运尽可能多的货,就应该尽可能走承受力较大的路。
因此如果这两个点联通,货车一定是在这些点构成的最大生成树上行走更优。
于是问题抽象为:n个点m条边的一个无向有权图(其实是许多树构成的森林)
求任意两个点之间的最短路径上权值最小的那条边的权值。
先使用kruscal算法得到由最大生成树构成的森林。
对于每一组询问,首先使用并查集看一下这两个点是否在一棵树上
不在的话直接输出-1,如果在,就使用倍增LCA算法求出结果。
这里还要预处理出 点x到(点x的2^k的祖先)的路径中的最小值
sum[x][0]=val[to[i]];
sum[x][i]=min(sum[x][i-1],sum[fa[x][i-1]][i-1]);
在LCA过程中求出路径最小值即可
然而一开始设为sum[10011][20],fa[10011][20] 当temp=20时数组越界导致狂WA不止 下次一定要开到 30 QAQ
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct your
{
int x,y,val;
}a[50010];
struct tree
{
int next,to,val;
}b[100100];
int head[10010];
int fa[10011][21];
int deep[10010];
int sum[10011][21];
int f[10011];
bool book[10011];
int n,m;
int find(int x)
{
return (f[x]==x)?x:f[x]=find(f[x]);
}
int tot;
void add(int x,int y,int v)
{
b[++tot].next=head[x];
b[tot].to=y;
b[tot].val=v;
head[x]=tot;
}
void klu()
{
int ans=0;
int cnt=0;
for(int i=1;i<=m;i++)
{
int dx=find(a[i].x),dy=find(a[i].y);
if(dx!=dy)
{
f[dx]=dy;
add(a[i].x,a[i].y,a[i].val);
add(a[i].y,a[i].x,a[i].val);
cnt++;
ans+=a[i].val;
}
if(cnt==n-1) return ;
}
}
void dfs(int x,int temp)
{
book[x]=true;
fa[x][0]=temp;
deep[x]=deep[temp]+1;
for(int i=1;fa[x][i-1];i++)
{
fa[x][i]=fa[fa[x][i-1]][i-1];
sum[x][i]=min(sum[x][i-1],sum[fa[x][i-1]][i-1]);
}
for(int i=head[x];i;i=b[i].next)
{
if(b[i].to==temp)continue;
sum[b[i].to][0]=b[i].val;
dfs(b[i].to,x);
}
}
void Swp(int &x,int &y)
{
int tmp=x;
x=y;y=tmp;
return;
}
int lca(int x,int y)
{
int nmp=0x7f7f7f7f;
if(deep[x]<deep[y]) Swp(x,y);
int temp=20;
while(temp>=0)
{
if(deep[fa[x][temp]]>=deep[y])
nmp=min(nmp,sum[x][temp]),x=fa[x][temp];
temp--;
}
if(x==y) return nmp;
temp=20;
while(temp>=0)
{
if(fa[x][temp]!=fa[y][temp])
{
nmp=min(nmp,sum[x][temp]);
nmp=min(nmp,sum[y][temp]);
x=fa[x][temp],y=fa[y][temp];
}
temp--;
}
nmp=min(sum[x][0],nmp);
nmp=min(sum[y][0],nmp);
return nmp;
}
void init()
{
memset(sum,0x3f,sizeof sum);
for(int i=1;i<=n;i++) f[i]=i;
}
bool cmp(your j,your k)
{
return j.val>k.val;
}
int q;
int main()
{
scanf("%d%d",&n,&m);
init();
for(int i=1;i<=m;i++)
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].val);
sort(a+1,a+m+1,cmp);
klu();
for(int i=1;i<=n;i++)
if(!book[i])dfs(i,0);
scanf("%d",&q);
for(int i=1;i<=q;i++)
{
int x,y;
scanf("%d%d",&x,&y);
int dx=find(x),dy=find(y);
if(dx!=dy) printf("-1\n");
else printf("%d\n",lca(x,y));
}
}