HDU 1879

#include <cstdio>  
#include <stdlib.h>  
#include <string.h>  
  
#include <algorithm>  
using namespace std ;  
  
#define MEM(a, v)       memset (a, v, sizeof (a))   // a for address, v for value  
#define max(x, y)       ((x) > (y) ? (x) : (y))  
#define min(x, y)       ((x) < (y) ? (x) : (y))  
  
#define INF     (0x3f3f3f3f)  
#define MAXN    (103)  
#define MAXE    (MAXN*(MAXN-1)/2)  
  
#define DEBUG   /##/  
  
struct EDGE {  
    int u, v, w ;  
    bool operator< (const EDGE &e) {  
        return w < e.w ;  
    }  
};  
  
int     n, m, edgeCnt ;  
int     set[MAXN] ;  
int     map[MAXN][MAXN] ;  
  
EDGE    edge[MAXE] ;  
  
void init_kruskal()  
{  
    int i ;  
    for (i = 1 ; i <= n ; ++i)  
        set[i] = i ;  
    edgeCnt = 0 ;  
}  
  
int find (int x)  
{  
    if (x == set[x])  
        return x ;  
    return set[x] = find(set[x]) ;  
}  
  
inline void merge (int x, int y)  
{  
    set[x] = set[y] ;  
}  
  
int kruskal ()  
{  
    int i, sum ;  
  
    sort (edge, edge+m) ;  
  
    sum = 0 ;   // 没初始化,WA  
    for (i = 0 ; i < m ; ++i)  
    {  
        if (n-1 <= edgeCnt) //这里的话,<= 和 == 在hdu结果是一样的  
            break ;  
  
        int x = find (edge[i].u) ;  
        int y = find (edge[i].v) ;  
  
        if (x != y)  
        {  
            merge (x, y) ;  
            ++edgeCnt ;  
            sum += edge[i].w ;  
        }  
    }  
    return sum ;  
}  
  
int main ()  
{  
    int i, b ;  
  
    while (scanf ("%d", &n), n)  
    {  
        m = n*(n-1)/2 ;  
        // 初始化,跟之前的模板题不同,这题要先初始化(个人的想法)  
        init_kruskal() ;  
  
        for (i = 0 ; i < m ; ++i)  
        {  
            scanf ("%d%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w, &b) ;  
            if (b) //对于已经建成的路,就检查是否在集合中  
            {  
                int x = find(edge[i].u) ;  
                int y = find(edge[i].v) ;  
                if (x != y) //若不在同一个集合,就合并集合  
                {  
                    merge (x, y) ;  
                    ++edgeCnt ; // 别忘了边数也要递增  
                }  
                --i, --m ; // 放到了 find(edge[i].u) 前面,WA  
            }  
        }  
          
        printf ("%d\n", kruskal()) ;  
    }  
    return 0 ; 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值