试题编号: | 201412-4 |
试题名称: | 最优灌溉 |
时间限制: | 1.0s |
内存限制: | 256.0MB |
问题描述: | 问题描述 雷雷承包了很多片麦田,为了灌溉这些麦田,雷雷在第一个麦田挖了一口很深的水井,所有的麦田都从这口井来引水灌溉。 输入格式 输入的第一行包含两个正整数n, m,分别表示麦田的片数和雷雷可以建立的水渠的数量。麦田使用1, 2, 3, ……依次标号。 输出格式 输出一行,包含一个整数,表示灌溉所有麦田所需要的最小费用。 样例输入 4 4 样例输出 6 样例说明 建立以下三条水渠:麦田1与麦田2、麦田2与麦田4、麦田4与麦田3。 评测用例规模与约定 前20%的评测用例满足:n≤5。 |
#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <time.h>
#include <vector>
#include <list>
using namespace std;
//201412-4 最优灌溉
struct Tree {
int from, to;
long long value;
};
//并查集(union-find sets)
int Par[1001], Rank[1001]; //父节点,树深度
void Make_Set(int N)
{
for (int i = 0; i < N; i++)
{
Par[i] = i;
Rank[i] = 0;
}
}
int Find_Set(int x)
{
if (Par[x] == x)
return x;
else
return Find_Set(Par[x]);
}
int Union(int x, int y)
{
static int num = 0;
x = Find_Set(x);
y = Find_Set(y);
if (x == y)
return 0;
num++;
if (Rank[x] < Rank[y])
Par[x] = y;
else
{
Par[y] = x;
if (Rank[x] == Rank[y])
Rank[x]++;
}
return num;
}
//Kruskal最小生成树算法
bool cmp(Tree x, Tree y)
{
return x.value < y.value;
}
long long Kruskal(Tree *first, int N, int M)
{
int num;
long long cost = 0;
Make_Set(N);
sort(first, first + M, cmp);
for (int i = 0; i < M; i++)
{
num = Union((*(first + i)).from, (*(first + i)).to);
if (num != 0)
{
cost += (*(first + i)).value;
if (num == N) //所有节点已全部遍历
break;
}
}
return cost;
}
int main()
{
int i, j, N, M;
cin >> N >> M;
vector<Tree>Data(M);
for (i = 0; i < M; i++)
{
cin >> Data[i].from >> Data[i].to >> Data[i].value;
}
long long Result = Kruskal(&Data[0], N, M);
cout << Result;
cin >> N;
return 0;
}