货车运输(最大生成树,LCA)
Posted ppxppx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了货车运输(最大生成树,LCA)相关的知识,希望对你有一定的参考价值。
题意:A国有n座城市,编号从1到n,城市之间有m条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有q辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物?
分析:显然限重就是边权.构建出图的最大生成树,然后树上每个节点dfs预处理出f[v][0]和dis[v][0],分别表示节点v的(2^0)级祖先(即父节点)是谁以及它到父节点的距离;然后对于每一个询问,利用倍增思想在树上LCA.
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
return s*w;
}
int n,m,Q;
int f[10005][21],dis[10005][21],visit[10005],deep[10005];
int tot,head[10005],nxt[20005],to[20005],w[20005],fa[10005];
struct EDGE{
int from,to,w;
}e[50005];
inline void add(int a,int b,int c){
tot++;nxt[tot]=head[a];head[a]=tot;to[tot]=b;w[tot]=c;
tot++;nxt[tot]=head[b];head[b]=tot;to[tot]=a;w[tot]=c;
}
bool cmp(const EDGE &a,const EDGE &b){return a.w>b.w;}
inline int find(int x){
if(x==fa[x])return x;
return fa[x]=find(fa[x]);
}
inline void kruskal(){
int k=0;
sort(e+1,e+m+1,cmp);
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=m;i++){
int a=find(e[i].from),b=find(e[i].to);
if(a!=b){
add(a,b,e[i].w);
fa[b]=a;
k++;
if(k==n-1)break;
}
}
return;
}
void dfs(int u){
visit[u]=1;
for(int i=head[u];i;i=nxt[i]){
int v=to[i];
if(visit[v])continue;
deep[v]=deep[u]+1;
f[v][0]=u;dis[v][0]=w[i];
dfs(v);
}
return;
}
int lca(int x,int y){
int ans=1e9;
if(deep[x]<deep[y])swap(x,y);
for(int i=20;i>=0;i--){
if(deep[f[x][i]]>=deep[y]){
ans=min(ans,dis[x][i]);//一定先更新ans,再让x,y往上跳,下面同理.
x=f[x][i];
}
}
if(x==y)return ans;
for(int i=20;i>=0;i--){
if(f[x][i]!=f[y][i]){
ans=min(ans,min(dis[x][i],dis[y][i]));
x=f[x][i];y=f[y][i];
}
}
ans=min(ans,min(dis[x][0],dis[y][0]));
return ans;
}
int main(){
n=read();m=read();
for(int i=1;i<=m;i++){
e[i].from=read();
e[i].to=read();
e[i].w=read();
}
kruskal();//构建最大生成树
for(int i=1;i<=n;i++){
if(visit[i])continue;
deep[i]=1;
dfs(i);
f[i][0]=i;dis[i][0]=1e9;
}//预处理,有些点不一定连通(即有可能是森林)
for(int j=1;j<=20;j++)
for(int i=1;i<=n;i++){
f[i][j]=f[f[i][j-1]][j-1];
dis[i][j]=min(dis[i][j-1],dis[f[i][j-1]][j-1]);
}//LCA的预处理
Q=read();
while(Q--){
int x=read(),y=read();
if(find(x)!=find(y))puts("-1");
else printf("%d
",lca(x,y));
}
return 0;
}
以上是关于货车运输(最大生成树,LCA)的主要内容,如果未能解决你的问题,请参考以下文章
洛谷T1967 货车运输 Kruskal最大生成树&&倍增LCA
$Noip2013/Luogu1967$ 货车运输 最大生成树+倍增$lca$