2730750 | 2008-01-23 13:12:47 | Accepted | 1542 | C++ | 00:00.24 | 728K | C.D. |
求最大边最短的生成树。
我怀疑即为最小生成树【?】。因为假如按照Prim算法,每次求得的都为一个集合到另一个集合的最短边,也就是不可能生成两棵树,一颗三条边为2,2,2,一颗为1,1,3;这样的情况应该会产生1,1,2 的生成树。【未严格证明】
但是在求最大边的时候,显然是用排序+并查集更易得到结果。
值得注意的是几点。
1.在unionset操作里使用了不同的返回值分辨不同的处理情况。
2.qsort的处理。
/*
zoj 1542
author: Crux.D
date: 2008.1.23
description: mst, kruscal, n-1 edge
*/
#include <cstdio>
#include <string>
#include <cstdlib>
typedef struct
{
int t1, t2, l;
} Con;
Con hub[15000], ans[1001];
int N, M, ans_num, max_len; // hub个数,connection数量,生成树边数(N-1),最大边长度
int cmp ( const void *a, const void *b )
{
Con *A = ( Con* ) a;
Con *B = ( Con* ) b;
if ( A->l == B->l )
{
if ( A->t1 == B->t1 )
return A->t2 > B->t2;
return A->t1 > B->t1;
}
return A->l > B->l;
}
void pt ()
{
int i;
for ( i = 0; i < M; i ++ )
{
printf ( "%d %d %d\n", hub[i].t1, hub[i].t2, hub[i].l );
}
}
int p[1001], num[1001];
void init_set ()
{
int i;
for ( i = 0; i <= N; i ++ )
{
p[i] = -1;
num[i] = 1;
}
}
int find_set ( int n )
{
int pre = n;
while ( p[pre] != -1 )
pre = p[pre];
int root = pre;
while ( n != root )
{
int t = p[n];
p[n] = root;
n = t;
}
return root;
}
int union_set ( int n1, int n2 )
{
int t1 = find_set ( n1 );
int t2 = find_set ( n2 );
if ( t1 == t2 )
return 0;
if ( num[t1] < num[t2] )
{
num[t2] += num[t1];
p[t1] = t2;
}
else
{
num[t1] += num[t2];
p[t2] = t1;
}
return 1;
}
void init ()
{
int i;
for ( i = 0; i < M; i ++ )
{
scanf ( "%d %d %d", &hub[i].t1, &hub[i].t2, &hub[i].l );
}
qsort ( hub, M, sizeof ( hub[0] ), cmp );
init_set ();
ans_num = 0;
//pt ();
}
void build_mst ()
{
int i;
int cur_cab = hub[0].l;
for ( i = 0; i < M; i ++ )
{
int v1 = hub[i].t1, v2 = hub[i].t2, len = hub[i].l;
if ( union_set ( v1, v2 ) == 1 ) //表示可以归并,边加入后不会造成回路
{
ans[ans_num].t1 = v1;
ans[ans_num].t2 = v2;
ans[ans_num ++].l = len;
}
if ( ans_num == N - 1 )
{
max_len = len;
break;
}
}
}
void print ()
{
printf ( "%d\n%d\n", max_len, ans_num );
int i;
for ( i = 0; i < ans_num; i ++ )
{
printf ( "%d %d\n", ans[i].t1, ans[i].t2 );
}
}
int main ()
{
//freopen ( "in.txt", "r", stdin );
while ( scanf ( "%d %d", &N, &M ) != EOF )
{
init ();
build_mst ();
print ();
}
return 0;
}
评论