货车运输(洛谷P1967)——生成树+倍增LCA的一通乱搞

Posted |斗蜂|

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了货车运输(洛谷P1967)——生成树+倍增LCA的一通乱搞相关的知识,希望对你有一定的参考价值。

---恢复内容开始---

题目原址在下面:

??

题目大意:n个点m条边每次询问两点之间路径的最小值的最大值。

思路:先跑一遍Kruskal,将边权从大到小排序,然后选n-1条边。之后跑倍增LCA。

#include<bits/stdc++.h>
using namespace std;
const int P=30;
struct nob{
	int sta,ed,val,jump;
}a[2000001],b[2000001];
int n,m,num=0,f[1000001],tot=0,jump[1000001]={0},fa[1000001][30],root;
int deep[1000001],qe,mina[1000001][30];
bool judge[1000001]={0};
bool mmp(nob a,nob b){
	return a.val>b.val;
}
void add(int sta,int ed,int val){
	num++;
	a[num].sta=sta;
	a[num].ed=ed;
	a[num].val=val;
}
void ad(int sta,int ed,int val){
	tot++;
	b[tot].sta=sta;
	b[tot].ed=ed;
	b[tot].val=val;
	b[tot].jump=jump[sta];
	jump[sta]=tot;
}
int find(int x){
	if (x==f[x]) return x;
	f[x]=find(f[x]);
	return f[x];
}
void dfs(int pos){
	judge[pos]=true;
	for (int i=jump[pos]; i; i=b[i].jump){
		if (!judge[b[i].ed]){
			fa[b[i].ed][0]=pos;
			mina[b[i].ed][0]=b[i].val;
			deep[b[i].ed]=deep[pos]+1;
//			judge[a[i].ed]=1;
			dfs(b[i].ed);
		}
	}
}
void bz(){
	for (int i=1; i<P; i++){
		for (int l=1; l<=n; l++){
			fa[l][i]=fa[fa[l][i-1]][i-1];
			mina[l][i]=min(mina[l][i-1],mina[fa[l][i-1]][i-1]);
		}
	}
}
int LCA(int x,int y){
	int rem=1e9;
	if (deep[x]<deep[y])
	swap(x,y);
	int d=deep[x]-deep[y];
	for (int i=0; i<P; i++)
		if ((1<<i)&d){
			rem=min(rem,mina[x][i]);
			x=fa[x][i];
		}
	if (x==y) return rem;
	for (int i=P-1; i>=0; i--){
		if (fa[x][i]!=fa[y][i]){
			rem=min(rem,mina[x][i]);
			rem=min(rem,mina[y][i]);
			x=fa[x][i];
			y=fa[y][i];
		}
	}
	rem=min(rem,mina[x][0]);
	rem=min(rem,mina[y][0]);
	return rem;
}
int main(){
	scanf("%d%d",&n,&m);
	for (int i=1,x,y,val; i<=m; i++){
		scanf("%d%d%d",&x,&y,&val);
		add(x,y,val);
		add(y,x,val);
	}
	sort(a+1,a+1+num,mmp);
	for (int i=1; i<=n; i++)
		f[i]=i;
	for (int i=1; i<=num; i++){
		if (find(a[i].sta)!=find(a[i].ed)){
			f[find(a[i].sta)]=find(a[i].ed);
			ad(a[i].sta,a[i].ed,a[i].val);
			ad(a[i].ed,a[i].sta,a[i].val);
		}
	}
	for (int i=1; i<=n; i++){
		if (f[i]==i){
			deep[i]=1;
			judge[i]=true;
			dfs(i);
		}
	}
	bz();
	scanf("%d",&qe);
	for (int i=1,x,y; i<=qe; i++){
		cin>>x>>y;
		if (find(x)!=find(y)){
			printf("-1\n");
			continue;
		}
		printf("%d\n",LCA(x,y));
	}
	return 0;
}

以上是关于货车运输(洛谷P1967)——生成树+倍增LCA的一通乱搞的主要内容,如果未能解决你的问题,请参考以下文章

luogu P1967 货车运输 最大生成树 倍增LCA

洛谷P3379lca,HDU2586,洛谷P1967货车运输,倍增lca,树上倍增

洛谷 P1967 货车运输生成树+树剖/LCA

洛谷P1967货车运输

洛谷 P1967 货车运输 Label: 倍增LCA && 最小瓶颈路

Luogu P1967 货车运输题解