现在的位置: 首页 > 综合 > 正文

poj3522 – Slim Span

2013年01月05日 ⁄ 综合 ⁄ 共 1292字 ⁄ 字号 评论关闭

                                  想看更多的解题报告:
http://blog.csdn.net/wangjian8006/article/details/7870410
                                     转载请注明出处:
http://blog.csdn.net/wangjian8006

题目大意:有N个节点,M条无向边的一个图,求在这个图中所有的生成树中,权值最大边减去权值最小边的最小值,如果不能构成一颗生成树没有就输出-1
解题思路:由于N与M都不大,所以对M条边排序后枚举边的起始点,kruscal后看能不能构成一颗生成树,可以的话判断最大边-最小边

 

/*
Memory 232K
Time   94MS
*/
#include <iostream>
using namespace std;
#define MAXM 5000
#define MAXV 105
#define inf 1<<29

typedef struct{
	int s,t,w;
}Edge;

Edge edge[MAXM];
int n,m,ans,set[MAXV];

int find(int x){
	if(x==set[x])
		return x;
	else{
		int rt=find(set[x]);
		set[x]=rt;
		return set[x];
	}
}

bool TUnion(int a,int b){
	int fa=find(a);
	int fb=find(b);
	if(fa==fb) return false;
	set[fb]=fa;
	return true;
}

void kruskal(int start){
	int i,min=inf,max=-1,s,t,w,cnt=0;

	for(i=0;i<=n;i++) set[i]=i;
	
	for(i=start;i<m;i++){
		s=edge[i].s;
		t=edge[i].t;
		w=edge[i].w;
		if(TUnion(s,t)){
			if(w<min) min=w;
			if(w>max) max=w;
			cnt++;
			if(cnt==n-1) break;
		}
	}
	if(cnt!=(n-1)) return ;
	if(ans>max-min) ans=max-min;
}

int cmp(const void *a,const void *b){
	return (*(Edge *)a).w-(*(Edge *)b).w;
}

bool work(){
	int i;
	ans=inf;
	kruskal(0);
	if(ans==inf) return false;
	for(i=1;i<m;i++) kruskal(i);
	return true;
}

int main(){
	int i;
	while(scanf("%d%d",&n,&m) && (n || m)){
		for(i=0;i<m;i++) scanf("%d%d%d",&edge[i].s,&edge[i].t,&edge[i].w);
		qsort(edge,m,sizeof(edge[0]),cmp);
		if(!work()) printf("-1\n");
		else printf("%d\n",ans);
	}
	return 0;
}

 

 

抱歉!评论已关闭.