枚举最小边,用kruskal求生成树,不断更新最小值就可以了。
给定一个简单图,n个点,m条边( 1<=n<=100,0 ≤ m ≤ n(n − 1)/2 ),要求一颗生成树,使得其最大边与最小边的差值是所有生成树中最小的,输出最小的那个差值。
分析:
类似于kruskal算法求最小生成树,将所有边按权值大小排升序,e1,e2,e3,...em。
枚举每条边ei,对ei,ei+1,ei+2,ei+3...进行求生成树,不断更新差值得到最优值。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
#define mpair make_pair
#define pii pair<int,int>
#define MM(a,b) memset(a,b,sizeof(a));
typedef long long lld;
typedef unsigned long long u64;
template<class T> bool up_max(T& a,const T& b){return b>a? a=b,1 : 0;}
template<class T> bool up_min(T& a,const T& b){return b<a? a=b,1 : 0;}
#define maxn
int n,m;
struct Edge{
int u,v,w;
void read(){
scanf("%d%d%d", &u, &v, &w);
}
bool operator<(Edge b)const{
return w<b.w;
}
} edge[10050];
const int inf= 200000000;
int fa[110];
int find(int x){
if( x==fa[x] ) return x;
else return fa[x]= find( fa[x] );
}
int solve(){
int ans= inf;
for(int k=1;k<=m;++k){
for(int i=1;i<=n;++i) fa[i]= i;
int mmin= inf, mmax= -inf;
int cnt= 0;
for(int i=k;i<=m;++i){
int x= edge[i].u, y= edge[i].v;
int fx= find(x), fy= find(y);
if( fx!=fy ){
fa[fy]= fx;
up_min( mmin, edge[i].w );
up_max( mmax, edge[i].w );
if( ++cnt == n-1 ) break;
if( mmax-mmin >= ans ) break; ///
}
}
if( cnt == n-1 ) up_min( ans, mmax-mmin );
}
return ans;
}
int main()
{
while( cin>>n>>m, (n+m) ){
for(int i=1;i<=m;++i)
edge[i].read();
sort( edge+1, edge+1+m );
int ans= solve();
if( ans!=inf ) cout<< ans <<endl;
else puts("-1");
}
}
poj 3522(求最小生成树,使得最边和最小边差最小)
最新推荐文章于 2019-08-08 16:23:47 发布