题意:给出n个点和m条边,求出最小生成树,输出最小生成树权值最大的第一条边,然后再输出最小生成树的边数,以及每一条边
//AC
//356K 94MS
#include <stdio.h>
#include <stdlib.h>
#define DEBUG puts("Here") ;
#define N 1005 // N 定点数上限
#define M 15005 // M 边数上限
int father[N] ;
int rank[N] ;
typedef struct Node //每条边的相关信息
{
int x , y ;
int val ;
}node ;
node gather[M] ;
struct ans //路径
{
int x , y ;
}path[M] ;
void Init_Father ( int const n )
{
int i ;
for ( i = 0 ; i <= n ; i ++ )
{
father[i] = i ;
}
}
/*
int Find_Father ( int x )
{
return x == father[x] ? x : Find_Father ( father[x] ) ;
}
*/
int Find_Father ( int x ) //查找父节点 比写成上面的递归更有效率,因为少了进栈出栈操作
{
while ( x != father[x] )
{
x = father[x] ;
}
return x ;
}
void Union ( int x , int y ) //合并节点
{
if ( x == y )
{
return ;
}
else if ( rank[x] > rank[y] )
{
father[x] = y ;
}
else
{
if ( rank[x] == rank[y] )
{
rank[y] ++ ;
}
father[y] = x ;
}
}
int cmp ( const void * a , const void * b ) //按val将node数组排序,以便以后贪心
{
return (*(node * )a ).val - (*(node *) b ).val ;
}
void Kruskal ( int const m )
{
qsort ( gather , m , sizeof ( gather[0] ) , cmp ) ;
int max ;
max = -1 ;
int index ; //index 记录path数组的索引
index = 0 ;
int i ;
for ( i = 0 ; i < m ; i ++ )
{
int x , y ;
x = Find_Father ( gather[i].x ) ;
y = Find_Father ( gather[i].y ) ;
if ( x != y )
{
Union ( x , y ) ;
path[index].x = gather[i].x ;
path[index++].y = gather[i].y ;
if ( max < gather[i].val )
{
max = gather[i].val ;
}
}
}
printf ("%d\n" , max ) ;
printf ("%d\n" , index ) ;
for ( i = 0 ; i < index ; i ++ ) //输出路径
{
printf ("%d %d\n" , path[i].x , path[i].y ) ;
}
}
int
main ( )
{
int n , m ; //n 为定点数 ,m 为边数
scanf ("%d%d" , & n , & m ) ;
int i ;
for ( i = 0 ; i < m ; i ++ )
{
scanf ("%d%d%d" , & gather[i].x , & gather[i].y , & gather[i].val ) ;
}
Init_Father ( n ) ;
Kruskal ( m ) ;
return 0 ;
}
============================分割线============================
//未AC
#include <stdio.h>
#define N 1005 // N 定点数上限
#define M 15005 // M 边数上限
#define MAX_DIS 1000 * 10000
int dis_betw[N][N] ; //邻接表
int low_dis[N] ; //未在最小生成树中的点到i的最短路集合
int flag[N] ;
struct Node
{
int x1 , x2 ;
}node[N] ;
void Init_Flag ( )
{
int i ;
for ( i = 0 ; i < N ; i ++ )
{
flag[i] = 0 ;
}
}
void Init_Dis_Betw ( )
{
int i ;
for ( i = 0 ; i < N ; i ++ )
{
int j ;
for ( j = 0 ; j < N ; j ++ )
{
dis_betw[i][j] = MAX_DIS ;
}
}
}
void Init_Low_Dis ( )
{
int i ;
for ( i = 0 ; i < N ; i ++ )
{
low_dis[i] = MAX_DIS ;
}
}
void Prim ( int const n ) //Prim模板
{
int s ;
s = 1 ;
Init_Flag ( ) ;
Init_Low_Dis ( ) ;
flag[s] = 1 ;
int index ;
index = 0 ;
int prim_weight ;
prim_weight = 0 ;
int m_max ;
m_max = -1 ;
int m = 1 ;
int new_point ;
int new_weight ;
while ( m < n )
{
new_weight = MAX_DIS ;
node[index].x1 = s ;
int i ;
for ( i = 1 ; i <= n ; i ++ )
{
if ( 0 == flag[i] && low_dis[i] > dis_betw[s][i] )
{
low_dis[i] = dis_betw[s][i] ;
}
if ( 0 == flag[i] && new_weight > low_dis[i] )
{
new_weight = low_dis[i] ;
new_point = i ;
}
}
s = new_point ;
node[index++].x2 = s ;
flag[s] = 1 ;
prim_weight += new_weight ;
if ( m_max < new_weight )
{
m_max = new_weight ;
}
m ++ ;
}
printf ("%d\n" , m_max ) ;
printf ("%d\n" , prim_weight ) ;
int i ;
for ( i = 0 ; i < index ; i ++ )
{
printf ("%d %d\n" , node[i].x1 , node[i].x2 ) ;
}
}
int
main ( )
{
int n , m ;
scanf ("%d%d" , & n , & m ) ;
Init_Dis_Betw ( ) ;
int i ;
for ( i = 0 ; i < m ; i ++ )
{
int x1 , x2 , val ;
scanf ("%d%d%d" , & x1 , & x2 , & val ) ;
dis_betw[x1][x2] = dis_betw[x2][x1] = val ;
}
Prim ( n ) ;
return 0 ;
}
Krustal过了。。。但我又写了个Prim未过 ,
网上说:Prim和Kruscal同样求最小生成树,但是Kruscal求出的生成树满足一个特性:这个生成树的最长边是尽量短的。。。
思考,未果,求大神路过指导。。