倍增+最小生成树 16pts求调
查看原帖
倍增+最小生成树 16pts求调
1486095
sunnybear楼主2025/8/29 17:23
//P1967双倍经验
#include <bits/stdc++.h>
using namespace std;
const int N=5e5+5;
struct node
{
	int u,v,w;
};
struct node2
{
	int v,w;
};
int n,m;
int ts;
int fa[N][25];
int dp[N][25];
int dep[N];
vector<node> t;
vector<node2>t2[N];
int f[N];
bool vis[N];
int find(int x)
{
	return f[x]=f[x]==x?x:find(f[x]);
}
bool cmp(node a,node b)
{
	return a.w<b.w;
}
void kruskal()
{
	sort(t.begin(),t.end(),cmp);//最小生成树
	for(int i=1; i<=n; i++) f[i]=i;
	for(int i=0; i<m; i++)
	{
		int fu=find(t[i].u);
		int fv=find(t[i].v);
		if(fu!=fv)
		{
			f[fu]=fv;
			t2[fv].push_back({fu,t[i].w});
			t2[fu].push_back({fv,t[i].w});
		}
	}
}
void dfs(int u)
{
	vis[u]=1;
	for(auto [v,w]:t2[u])
	{
		if(!dep[v])
		{
			dep[v]=dep[u]+1;
			fa[v][0]=u;
			dp[v][0]=w;
			dfs(v);
		}
	}
}
void pre()
{
	for(int i=1; i<=20; i++)
	{
		for(int j=1; j<=n; j++)
		{
			fa[j][i]=fa[fa[j][i-1]][i-1];
			dp[j][i]=min(dp[j][i-1],dp[fa[j][i-1]][i-1]);
		}
	}
}
int LCA(int x,int y)
{
	if(find(x)!=find(y)) return -1;
	int ans=-1;
	if(dep[x]>dep[y]) swap(x,y);
	for(int i=20; i>=0; i--)
	{
		if(dep[fa[y][i]]>=dep[x])
		{
			ans=max(ans,dp[y][i]);
			y=fa[y][i];
		}
	}
	if(x==y) return ans;
	for(int i=20; i>=0; i--)
	{
		if(fa[x][i]!=fa[y][i])
		{
			ans=max({ans,dp[x][i],dp[y][i]});
			x=fa[x][i];
			y=fa[y][i];
		}
	}
	return max({ans,dp[x][0],dp[y][0]});
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int x,y,z,q;
	cin>>n>>m;
	for(int i=1; i<=m; i++)
	{
		cin>>x>>y>>z;
		t.push_back({x,y,z});
	}
	kruskal();
	for(int i=1; i<=n; i++)
	{
		if(!vis[i])
		{
			dep[i]=1;
			dfs(i);
		}
	}
	pre();
	cin>>q;
	while(q--)
	{
		cin>>x>>y;
		int ans=LCA(x,y);
		if(ans==-1) cout<<"impossible"<<endl;
		else cout<<ans<<endl;
	}
	return 0;
}

2025/8/29 17:23
加载中...