其他分享
首页 > 其他分享> > Bond

Bond

作者:互联网

题目链接

Bond

给定一张 \(n\) 个点 \(m\) 条边的无向图,每条边有一个权值,有 \(q\) 个询问,每次询问给出两个点 \((s,t)\),找到从一条从 \(s\) 到 \(t\) 的路径,使得最大权值最小,只需输出这个权值

解题思路

并查集按秩合并,最小生成树,ST

首先,可以肯定一点,这条路径一定可以是最小生成树上的一条唯一路径
定理:最小生成树是最小瓶颈生成树,但是最小瓶颈生成树不一定是最小生成树

可利用 kruskal 算法求出最小生成树,在利用和 \(CLA\) 类似的思想求出最小生成树上两点之间的最大权值

当然,在利用并查集求最小生成树时可以按秩合并,这样整棵树的高度为 \(O(logn)\) 级别,

代码

// Problem: Bond
// Contest: Virtual Judge - UVA
// URL: https://vjudge.net/problem/UVA-11354
// Memory Limit: 1024 MB
// Time Limit: 8000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
// #define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=5e4+5,M=1e5+5;
int n,m,q,s,t,tt,fa[N],h[N],d[N],f[N][20],mx[N][20];
vector<PII> adj[N];
struct A
{
	int a,b,w;
	bool operator<(const A &o)
	{
		return w<o.w;
	}
}a[M];
int find(int x)
{
	return x==fa[x]?x:fa[x]=find(fa[x]);
}
void merge(int x,int y)
{
	if(h[x]<h[y])
		fa[x]=y;
	else
	{
		fa[y]=x;
		if(h[x]==h[y])h[x]++;
	}
}
void kruskal()
{
	int cnt=0;
	sort(a+1,a+1+m);
	for(int i=1;i<=m;i++)
	{
		int x=a[i].a,y=a[i].b,w=a[i].w;
		int tx=x,ty=y;
		x=find(x),y=find(y);
		if(x==y)continue;
		cnt++;
		merge(x,y);
		adj[tx].pb({ty,w});
		adj[ty].pb({tx,w});
		if(cnt>=n-1)break;
	}
}
void bfs()
{
	queue<int> q;
	q.push(1);
	d[1]=1;
	while(q.size())
	{
		int x=q.front();
		q.pop();
		for(auto t:adj[x])
		{
			int y=t.fi,w=t.se;
			if(d[y])continue;
			d[y]=d[x]+1;
			f[y][0]=x;
			mx[y][0]=w;
			for(int i=1;i<=tt;i++)f[y][i]=f[f[y][i-1]][i-1],mx[y][i]=max(mx[y][i-1],mx[f[y][i-1]][i-1]);
			q.push(y);
		}
	}
}

int LCA(int x,int y)
{
	if(d[x]<d[y])swap(x,y);
	int res=0;
	for(int i=tt;i>=0;i--)
		if(d[f[x][i]]>=d[y])res=max(res,mx[x][i]),x=f[x][i];
	if(x==y)return res;
	for(int i=tt;i>=0;i--)
		if(f[x][i]&&f[x][i]!=f[y][i])res=max({res,mx[x][i],mx[y][i]}),x=f[x][i],y=f[y][i];
	return max({res,mx[x][0],mx[y][0]});
}
int main()
{
	help;
	int T=0;
    while(cin>>n>>m)
    {
    	for(int i=1;i<=n;i++)adj[i].clear(),h[i]=d[i]=0;
    	if(T)puts("");
    	T++;
    	tt=log(n)/log(2);
    	for(int i=1;i<=m;i++)cin>>a[i].a>>a[i].b>>a[i].w;
    	for(int i=1;i<=n;i++)fa[i]=i;
    	kruskal();
    	bfs();
    	cin>>q;
    	while(q--)
    	{
    		cin>>s>>t;
    		cout<<LCA(s,t)<<'\n';
    	}	
    }
    return 0;
}

标签:int,res,最小,生成,Bond,mx,define
来源: https://www.cnblogs.com/zyyun/p/16188383.html