Range minimum spanning tree

版权声明:copy right https://blog.csdn.net/qq_43521140/article/details/90672178

Example:
Slim Span POJ-3522
find the most comfortable road HDU-1598

Description:
Given an undirected weighted graph G, you should find one of spanning trees T specified as follows:
the difference between the largest weight and the smallest weight among the n - 1 edges of T is as small as possible.

Idea:
Use Kruskal algorithm.
After sorting the edges by their weight, enumerate the smallest edge of each spanning tree,and then update the difference between the largest edge and the smallest one when forming a spanning tree. So the minimum difference is the answer.
Note that the second example has q queries for every ’ u ’ to ’ v ', so each enumeration for the smallest edge stops when node u and node v are connected.

ACODE for example one:

#include<stdio.h>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<map>
using namespace std;
typedef long long ll;
const int MX = 2e4 + 7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
int n,m;
int pre[MX];
struct Edge
{
	int u,v;
	int w;
}e[MX << 1];
bool cmp(Edge a,Edge b){
	return a.w < b.w;
}
void init()
{
	for(int i = 1;i <= n;++i){
		pre[i] = i;
	}
}
int find(int x)
{
	if(pre[x] == x) return x;
	return pre[x] = find(pre[x]);
}
bool same(int x,int y)
{
	return find(x) == find(y);
}
void unionset(int x,int y)
{
	int f1 = find(x);
	int f2 = find(y);
	if(f1 == f2) return ;
	pre[f1] = f2;
}
int kruskal(){
	int ans = INF;
	int cont = 0;
	sort(e+1,e+1+m,cmp);
	for(int i = 1;i <= m;++i){
		cont = 0;
		init();
		int res = INF;
		for(int j = i;j <= m;++j){
			if(same(e[j].u,e[j].v)) continue;
			unionset(e[j].u,e[j].v);
			cont++;
			if(cont == n - 1){
				res = e[j].w - e[i].w;
				break;
			}
		}
		ans = min(ans,res);
	}
	return ans;
}
int main(int argc, char const *argv[])
{
	while(cin >> n >> m){
		if(n == 0 && m == 0) break;
		for(int i = 1;i <= m;++i){
			cin >> e[i].u >> e[i].v >> e[i].w;
		}
		int ans = kruskal();
		if(ans == INF) cout << -1 << endl;
		else cout << ans << endl;
	}
    return 0;
}

ACODE for example two:

#include<stdio.h>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
using namespace std;
typedef long long ll;
const int MX = 2e3 + 7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
int n,m;
int pre[MX << 1];
struct node
{
	int u,v;
	int w;
}e[MX << 1];
bool cmp(node a,node b)
{
	return a.w < b.w;
}
void init()
{
	for(int i = 1;i <= n;++i)
		pre[i] = i;
}
int find(int x)
{
	if(pre[x] == x) return x;
	return pre[x] = find(pre[x]);
}
bool same(int x,int y)
{
	return find(x) == find(y);
}
void unionset(int x,int y){
	int f1 = find(x);
	int f2 = find(y);
	if(f1 == f2) return ;
	pre[f1] = f2;
}
int kruskal(int u ,int v){
	int ans = INF;
	sort(e+1,e+1+m,cmp);
	for(int i = 1;i <= m;++i){
		init();
		for(int j = i;j <= m;++j){
			if(same(e[j].v,e[j].u)) continue;
			unionset(e[j].v,e[j].u);
			if(same(u,v)){
				ans = min(ans,e[j].w - e[i].w);
				break;
			}
		}
	}
	return ans;
}
int main(int argc, char const *argv[])
{
	while(cin >> n >> m){
		for(int i = 1;i <= m;++i){
			cin >> e[i].u >> e[i].v >> e[i].w;
		}
		int q;
		int u,v;
		cin >> q;
		while(q--){
			cin >> u >> v;
			int ans = kruskal(u,v);
			if(ans == INF) cout << -1 << endl;
			else cout << ans << endl;
		}
	}
    return 0;
}

PS:Please forgive me if any unprofessional and inaccurate English writing occurs to you.

猜你喜欢

转载自blog.csdn.net/qq_43521140/article/details/90672178