kruskal + LCA 求调 玄关
查看原帖
kruskal + LCA 求调 玄关
768270
__why楼主2024/6/22 15:13

输出全是-1,有理由怀疑是并查集,但是手推的时候并没有出错(悲

#include<bits/stdc++.h> 
using namespace std;
const int maxn = 1e4+5,maxm = 20;
const int inf = 1e9+5;

int n,m,q,pos,ans(inf);

int c[maxn][maxm],f[maxn][maxm],d[maxn];
int fa[maxn];

vector<pair<int,int> >g[maxn];

struct Edge{
	int x,y,value;
	bool operator < (const Edge& x) const {
		return value > x.value;
	}
}res[maxn];

priority_queue<Edge>que;

bool find(int x){return x == fa[x] ? x : fa[x] = find(fa[x]);}

void dfs(int u,int fa){
	d[u] = d[fa] + 1;
	f[u][0] = fa;
	c[u][0] = min(u,fa);
	for(int i = 1;i<20;i++){
		f[u][i] = f[f[u][i-1]][i-1];
		c[u][i] = min(c[u][i-1],c[f[u][i-1]][i-1]);
	}
	for(auto i : g[u]){
		if(i.first==fa)continue;
		int v = i.first,w = i.second;
		c[v][0] = w;
		dfs(i.first,u);
	}
}

int lca(int u,int v){
	if(d[u] < d[v])swap(u,v);
	for(int i = maxm - 1;i>=0;i--){
		if(d[f[u][i]]>=d[v]){
			ans = min(ans,c[u][i]);
			u = f[u][i];
		}
	}
	if(u==v)return u;
	for(int i = maxm - 1;i>=0;i--){
		if(f[u][i]!=f[v][i]){
			ans = min({c[u][i],c[v][i],ans});
			u = f[u][i];
			v = f[v][i];
		}
	}
	return min({c[u][0],c[v][0],ans});
}

int main(){
	cin>>n>>m;
	for(int i = 1,x,y,z;i<=m;i++){
		cin>>x>>y>>z;
		que.push({x,y,z});
	}
	//kruskal 
	for(int i = 1;i<=n;i++)fa[i] = i;
	
	for(int i = 1;i<=m;i++){
		Edge tmp = que.top();
		que.pop();
		int fx = find(tmp.x);
		int fy = find(tmp.y);
		if(fx==fy)continue;
		fa[fx] = fy;
		ans += tmp.value;
		res[++pos] = tmp;
		//存边 
	}
	//建树 
	
	for(int i = 1,x,y,z;i<=pos;i++){
		x = res[i].x;
		y = res[i].y;
		g[x].push_back({y,z});
		g[y].push_back({x,z});
	}
	
	for(int i = 1;i<=n;i++){
		if(!d[i])dfs(i,0);
	}
	
	cin>>q;
	
	for(int i = 1,u,v;i<=q;i++){
		cin>>u>>v;
		if(fa[u]!=fa[v])cout<<-1<<'\n';
		else{
			cout<<lca(u,v)<<'\n';
		}
	}
  //N-5保佑
}
2024/6/22 15:13
加载中...