现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。
输入格式:
输入数据包括城镇数目正整数N(≤1000)和候选道路数目M(≤3N);随后的M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。为简单起见,城镇从1到N编号。
输出格式:
输出村村通需要的最低成本。如果输入数据不足以保证畅通,则输出−1,表示需要建设更多公路。
输入样例:
6 15
1 2 5
1 3 3
1 4 7
1 5 4
1 6 2
2 3 4
2 4 6
2 5 2
2 6 6
3 4 6
3 5 1
3 6 1
4 5 10
4 6 8
5 6 3
输出样例:
12
#include <cstdio>
#include <algorithm>
#define MAX 1000
#define INF 0x3fffffff
using namespace std;
int N, M;
int MGraph[MAX][MAX];
int dist[MAX] = { 0 };
int parent[MAX] = { 0 };
int father[MAX] = { 0 };
typedef struct {
int start;
int end;
int weight;
} Edge;
Edge edge[MAX * 3] = { 0 };
void initMGraph() {
for( int i = 0; i < MAX; i++ )
for( int j = 0; j < MAX; j++ ) {
if( i == j ) MGraph[i][j] = 0;
else MGraph[i][j] = INF;
}
}
void insertEdge( int a, int b, int w ) {
MGraph[a][b] = w;
MGraph[b][a] = w;
}
/* Prim最小生成树算法 */
int prim() {
int ans = 0;
// 默认从0号顶点开始进行算法
for( int i = 0; i < N; i++ ) {
dist[i] = MGraph[0][i];
}
parent[0] = -1;
dist[0] = 0;
int min, v;
int cnt = 1;
while( 1 ) {
min = INF;
v = -1;
for( int i = 0; i < N; i++ ) {
if( dist[i] != 0 && dist[i] < min ) {
min = dist[i];
v = i;
}
}
if( v == -1 ) break;
ans = ans + min;
dist[v] = 0;
cnt++;
for( int i = 0; i < N; i++ ) {
if( MGraph[v][i] != INF && dist[i] != 0 ) {
if( MGraph[v][i] < dist[i] ) {
dist[i] = MGraph[v][i];
parent[i] = v;
}
}
}
}
//printf( "%d\n", cnt );
if( cnt < N ) {
return -1;
}
return ans;
}
void initSet() {
for( int i = 0; i < N; i++ )
father[i] = i;
}
int findFather( int x ) {
if( father[x] == x ) return x;
else return findFather( father[x] );
}
bool Union( int a, int b ) {
int fatherA = findFather( a );
int fatherB = findFather( b );
if( fatherA == fatherB ) return false;
else father[fatherA] = father[b];
return true;
}
int cmp( Edge a, Edge b ) {
return a.weight < b.weight ? 1 : 0;
}
int Kruskal() {
initSet();
sort( edge, edge + M, cmp );
int cnt = N;
int ans = 0;
for( int i = 0; i < M && cnt > 1; i++ ) {
if( Union( edge[i].start, edge[i].end ) ) {
ans = ans + edge[i].weight;
cnt--;
}
}
//printf( "%d\n", cnt );
if( cnt > 1 ) {
ans = -1;
}
return ans;
}
int main() {
initMGraph();
//freopen( "123.txt", "r", stdin );
scanf( "%d%d", &N, &M );
int a, b, w;
for( int i = 0; i < M; i++ ) {
scanf( "%d%d%d", &a, &b, &w );
insertEdge( a - 1, b - 1, w );
edge[i].weight = w;
edge[i].start = a - 1;
edge[i].end = b - 1;
}
//int ans = prim();
int ans = Kruskal();
printf( "%d", ans );
return 0;
}