POJ 1861 Network (最短路)

4 篇文章 0 订阅

题意:给出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求出的生成树满足一个特性:这个生成树的最长边是尽量短的。。。

思考,未果,求大神路过指导。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值