题意:
N个顶点的无向图,给你每条边的长度,要你求该图的最小生成树.其中每个点用大写字母A-Z表示.
分析:
第一次kruskal,直接模板即可,转换输入格式.注意输入中的边没有重复边,所以无需判重.
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 30;
const int maxm = 110;
struct Edge {
int u, v;
int dis;
bool operator< ( const Edge &rhs ) const { return dis < rhs.dis; }
};
struct Kruskal {
int n, m;
Edge edg[ maxm ]; //边的表
int fa[ maxn ]; //并查集
int findset ( int x ) { return fa[ x ] == -1 ? x : fa[ x ] = findset ( fa[ x ] ); }
void init ( int _n ) {
n = _n;
m = 0;
memset ( fa, -1, sizeof ( fa ) );
}
void AddEdge ( int u, int v, int dis ) { edg[ m++ ] = Edge{u, v, dis}; }
int kruskal () {
//总权值,总的边数
int sum = 0, cnt = 0;
// sort the edges of G.E into nondecreasing order by weight w
sort ( edg, edg + m );
// for each edge(u,v) in G.E taken in nondecreasing order by weight
for ( int i = 0; i < m; ++i ) {
int u = edg[ i ].u, v = edg[ i ].v;
// if FIND-SET(u) != FIND-SET(v)
if ( findset ( u ) != findset ( v ) ) {
sum += edg[ i ].dis;
// UNION ( u,v )
fa[ findset ( u ) ] = findset ( v );
if ( ++cnt >= n - 1 )
return sum;
}
}
return -1;
}
} KK;
int main () {
int n;
while ( ~scanf ( "%d", &n ) && n ) {
KK.init ( n );
for ( int i = 0; i < n - 1; ++i ) {
char s1[ 10 ], s2[ 10 ];
int k, v, d;
scanf ( "%s%d", s1, &k );
while ( k-- ) {
scanf ( "%s%d", s2, &d );
v = s2[ 0 ] - 'A';
KK.AddEdge ( i, v, d );
}
}
printf ( "%d\n", KK.kruskal () );
}
return 0;
}