POJ 2395 最小生成树的最大边

给定一个可以求出最小生成树的图,求最小生成树中边权值最大的边

做法,有 Kruskal 和  Prim 两种算法,Kruskal 适合稀疏图,Prim 适合稠密图。

Kruskal :47 ms  , 内存 0.8 MB

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std ;
typedef long long LL ;
int n , m , one , two , i ;
int father[2005] ;
struct Node{
	int src , des ;
	LL value ;
} Edge[10005] ;
bool cmp( const Node &a , const Node &b ){
	return a.value < b.value ;
}

int find( int u ){                     // 找祖先
	return u == father[u] ? u : father[u] = find( father[u] ) ;
}

int Merge( int a , int b ){            // 如果这两个点还不在一集合里,不会形成环  , return 1 ;
	one = find( a ) ;
	two = find( b ) ;
	if( one != two ){
		father[two] = one ;
		return 1 ;
	}
	return 0 ;
}

int main(){
	LL ans = 0 ;
	scanf( "%d%d" , &n , &m ) ;
	for( i = 0 ; i <= n ; ++i )     // 初始化祖先为自己
		father[i] = i ;
	for( i = 1 ; i <= m ; ++i )
		scanf( "%d%d%lld" , &Edge[i].src , &Edge[i].des , &Edge[i].value ) ;
	sort( Edge+1 , Edge+m+1 , cmp ) ;              // 从小到大排序
	for( i = 1 ; i <= m ; ++i )
		if( Merge( Edge[i].src , Edge[i].des ) )
			ans = max( ans , Edge[i].value ) ;
	printf( "%lld\n" , ans ) ;
	return 0 ;
}
Prim:125 ms , 内存 16.4 MB

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std ;
typedef pair<int,int> P ;
#define INF 1000000005
int n , m ;
int Gragh[2005][2005] ;       // 浪费空间
int ans , value , dis[2005] ;
int book[2005] ;

void Prim(){
	int u , i , j ;
	ans = 0 ;
	for( i = 1 ; i <= n ; ++i )
		dis[i] = Gragh[1][i] , book[i] = 0 ;
	dis[1] = 0 ;
	book[1] = 1 ;
	for( i = 2 ; i <= n ; ++i ){
		int Min = INF ;
		for( j = 1 ; j <= n ; ++j )
			if( !book[j] && dis[j] < Min )
				Min = dis[j] , u = j ;
		ans = max( ans , Min ) ;
		book[u] = 1 ;
		for( j = 1 ; j <= n ; ++j )
			if( !book[j] && dis[j] > Gragh[u][j] )
				dis[j] = Gragh[u][j] ;
	}
	cout << ans << endl ;
}

int main(){
	int i , j , src , des ;
	scanf( "%d%d" , &n , &m ) ;
	for( i = 1 ; i <= n ; ++i )
		for( j = 1 ; j <= n ; ++j )
			Gragh[i][j] = INF ;
	for( i = 1 ; i <= n ; ++i )  Gragh[i][i] = 0 ;
	for( i = 1 ; i <= m ; ++i ){
		scanf( "%d%d%d" , &src , &des , &value ) ;
		if( Gragh[src][des] > value )
			Gragh[src][des] = Gragh[des][src] = value ;  // 取最短的重边
	}
	Prim() ;
	return 0 ;
}

从上面看, Kruskal 比 Prim 要快,而且,占用内存少(这题因为有重边,所以采用邻接矩阵存储更方便 

Prim + 堆优化+邻接表 :63ms , 内存 1 MB 

#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <queue>
using namespace std ;
#define INF 1000000005
typedef pair<int,int> P ;
int n , m ;
int dis[2005] , book[2005] ;
int head[2005] , k ;
int To[10002<<1] , cost[10002<<1] , Next[10002<<1] ;  // 因为是无向图,双向存储,开两倍空间

void Add( int src , int des , int value ){
	To[++k] = des , cost[k] = value , Next[k] = head[src] , head[src] = k ;
	To[++k] = src , cost[k] = value , Next[k] = head[des] , head[des] = k ;
}

void Prim(){
	priority_queue< P , vector<P> , greater<P> > Q ;
	int i , u , v , w , ans = 0 ;
	for( i = 1 ; i <= n ; ++i )
		dis[i] = INF ;
	Q.push( P( dis[0] , 1 ) ) ;
	while( !Q.empty() ){
		P top = Q.top() ;
		Q.pop() ;
		u = top.second ;
		if( book[u] == 0 )  ans = max( ans , top.first ) ;// 即使有重边,因为是优先级队列,权更小的先出来,后面的重边不做处理。
		book[u] = 1 ;
		if( dis[u] < top.first )   
			continue ;
		for( i = head[u] ; i != -1 ; i = Next[i] ){
			v = To[i] , w = cost[i] ;
			if( dis[v] > w )
				Q.push( P( dis[v] = w , v ) ) ;
		}
	}
	cout << ans << endl ;
}

int main(){
	scanf( "%d%d" , &n , &m ) ;
	int i , src , des , value ;
	for( int i = 0 ; i <= n ; ++i ) head[i] = -1 ;
	for( i = 1 ; i <= m ; ++i ){
		scanf( "%d%d%d" , &src , &des , &value ) ;
		Add( src , des , value ) ;
	}
	Prim() ;
	return 0 ;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值