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.