求调 最大生成树+LCA
查看原帖
求调 最大生成树+LCA
575363
revolutionary_oier楼主2023/8/1 11:52
#include<bits/stdc++.h>
using namespace std;

const int maxn=1e4+10;
const int maxm=5e4+10;
const int inf=2e9;
int n,m,cnt,n1,q;
int fa[maxn],head[maxn],dis[maxn];
int f[maxn][20],mx[maxn][20];
bool use[maxm<<2],vis[maxn];
struct node{
	int u,v,w;
}c[maxm<<2];
struct edge{
	int v,nxt,w;
}e[maxm<<2];
inline void add(int u,int v,int w){
	c[++cnt].w=w;
	c[cnt].v=v;
	c[cnt].u=u;
}
inline bool cmp(node nx,node ny){return nx.w>ny.w;}
inline int find(int x){
	if(fa[x]==x)return x;
	return fa[x]=find(fa[x]);
}
inline bool merge(int x,int y){
	int p=find(x);
	int q=find(y);
	if(p==q)return false;
	fa[p]=q;
	return true; 
}
inline void Kruskal(){
	for(int i=1;i<=n;i++)fa[i]=i;
	n1=n;
	sort(c+1,c+cnt+1,cmp);
	for(int i=1;i<=cnt;i++){
		int u=c[i].u,v=c[i].v;
		if(merge(u,v)){
			--n1;
			use[i]=true;
			if(n1==1)break;
		}
	}
}
inline void add1(int u,int v,int w){
	e[++cnt].v=v;
	e[cnt].w=w;
	e[cnt].nxt=head[u];
	head[u]=cnt;
}
inline void dfs(int x,int father,int dep){
//	printf("mx[3][0] = %d\n",mx[3][0]);
	vis[x]=true;
	dis[x]=dep;
	f[x][0]=father;
	for(int i=1;i<=20;i++){
//		printf("ctrl = %d %d\n",x,i);
		f[x][i]=f[f[x][i-1]][i-1];
		mx[x][i]=min(mx[x][i],min(mx[f[x][i-1]][i-1],mx[x][i-1]));
	}
	for(int i=head[x];i;i=e[i].nxt){
		int v=e[i].v;
		if(v==father)continue;
		mx[v][0]=e[i].w;
//		printf("ctrl %d %d %d\n",v,0,e[i].w);
//			if(mx[3][0]==10638)printf("operator control = %d %d %d\n",x,father,dep);
//		if(v==3)printf("mx[3][0] = %d\n",e[i].w);
		dfs(v,x,dep+1);
	}
}
inline int LCA(int x,int y){
	if(dis[x]>dis[y])swap(x,y);
	int t=dis[y]-dis[x];
	for(int i=0;i<=20;i++){
		if(t&1)y=f[y][i];
		t>>=1;
	}
	if(x==y)return x;
	for(int i=20;i>=0;i--){
		if(f[x][i]!=f[y][i]){
			x=f[x][i];
			y=f[y][i];
		}
	}
	return f[x][0];
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);
	}
	//printf("cnt = %d\n",cnt);
	Kruskal();
//	for(int i=1;i<=m;i++){
//		if(use[i])printf("1");
//		else printf("0");
//	}	
//		printf("edge control\n");
//		for(int i=1;i<=cnt;i++){
//			if(use[i])printf("%d %d %d\n",c[i].u,c[i].v,c[i].w);
//		}
	cnt=0;
	for(int i=1;i<=m;i++){
		if(use[i]){
//			printf("1");
			add1(c[i].u,c[i].v,c[i].w);
			add1(c[i].v,c[i].u,c[i].w);
		}
//		else printf("0");
	}
//	printf("cnt = %d\n",cnt);
//	for(int i=1;i<=cnt;i++)printf("%d %d %d\n",e[i].v,e[i].nxt,e[i].w);
//	printf("\n");
	//printf("st = %d\n",st);
	//printf("%d\n",cnt);
	for(int i=1;i<=n;i++)dis[i]=inf;
	for(int i=0;i<=n;i++){
		for(int j=0;j<=20;j++)mx[i][j]=inf;
	}
	for(int i=1;i<=n;i++){
		if(!vis[i]){
			dfs(i,0,0);
//				printf("%d = I AK NOI\n",i);
		}
	}
//	printf("mx[3][0] = %d\n",mx[3][0]);
//	for(int i=1;i<=n;i++)printf("%d ",dis[i]);
//	printf("\n");
	scanf("%d",&q);
	while(q--){
		int u,v;
		scanf("%d%d",&u,&v);
		if(find(u)!=find(v)){
			printf("-1\n");
			continue;
		}
		int op=LCA(u,v);
		int ans=inf;
		int t=dis[u]-dis[op];
//		printf("%d %d %d\n",dis[op],dis[u],dis[v]);
//		printf("op = %d\n",op);
//		printf("%d ",t);
//		printf("%d %d %d\n",u,v,op);
		for(int i=0;i<=20;i++){
			if(t&1){
				ans=min(ans,mx[u][i]);
				u=f[u][i];
			}
			t>>=1;
		}
		t=dis[v]-dis[op];
//		printf("%d\n",t);
//		printf("fa[4][0] = %d\n",f[4][0]);
//		printf("fa[3][0] = %d\n",f[3][0]); 
		for(int i=0;i<=20;i++){
			if(t&1){
//				printf("mx[%d][%d] = %d\n",v,i,mx[v][i]);
				ans=min(ans,mx[v][i]);
//				printf("mx[%d][%d] = %d\n",v,i,mx[v][i]);
				v=f[v][i];
			}
			t>>=1;
		}
//		printf("operator = %d\n",mx[3][0]);
		printf("%d\n",ans);
	}
	return 0;
}
2023/8/1 11:52
加载中...