题目链接:http://www.bnuoj.com/v3/problem_show.php?pid=2496
题目描述:
Bessie has been hired to build a cheap internet network among Farmer John's N (2 <= N <= 1,000) barns that are conveniently numbered 1..N. FJ has already done some surveying, and found M (1 <= M <= 20,000) possible connection routes between pairs of barns. Each possible connection route has an associated cost C (1 <= C <= 100,000). Farmer John wants to spend the least amount on connecting the network; he doesn't even want to pay Bessie.
Realizing Farmer John will not pay her, Bessie decides to do the worst job possible. She must decide on a set of connections to install so that (i) the total cost of these connections is as large as possible, (ii) all the barns are connected together (so that it is possible to reach any barn from any other barn via a path of installed connections), and (iii) so that there are no cycles among the connections (which Farmer John would easily be able to detect). Conditions (ii) and (iii) ensure that the final set of connections will look like a "tree".
输入格式:
* Line 1: Two space-separated integers: N and M
* Lines 2..M+1: Each line contains three space-separated integers A, B, and C that describe a connection route between barns A and B of cost C.
输出格式:
* Line 1: A single integer, containing the price of the most expensive tree connecting all the barns. If it is not possible to connect all the barns, output -1.
输入样例:
5 8 1 2 3 1 3 7 2 3 10 2 4 4 2 5 8 3 4 6 3 5 2 4 5 17输出样例:
42分析思路:
用最小生成树Kruskal的做法,但按照大边排序,因为每次要去最大的,才能保证最后形成的树cost最大,不要忘记图不连通的情况,应该用并查集合并操作的次数来判定,当合并操作的次数为顶点数减一时,图就是连通的。最后犯了一个低级错误,开始是#define MAXN 1000 + 10,后面用到了G[MAXN*MAXN],这样G数组的大小实际为1000 + 10 * 1000 + 10,这样就RE了几次。。。
源代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 1010
struct Node {
int u, v, c;
Node (int u = 0, int v = 0, int c = 0) : u(u), v(v), c(c) {}
bool operator < (const Node &a) const {
return c > a.c;
}
};
Node G[MAXN*MAXN];
int father[MAXN], ranke[MAXN];
int fb[MAXN];
int N, M;
void Makeset(int nn) {
for (int i = 0; i <= nn; i++) {
father[i] = i;
ranke[i] = 1;
}
}
int Find(int r) {
if (r != father[r]) {
father[r] = Find(father[r]);
}
return father[r];
}
int Kruskal(int V, int E) {
int i, j;
int ans = 0, cnt = 0;
sort(G, G + E);
for (i = 0; i < E; i++) {
int fx = Find(G[i].u);
int fy = Find(G[i].v);
if (fx == fy) continue;
ans += G[i].c;
cnt++;
if (ranke[fx] >= ranke[fy]) {
father[fy] = fx;
ranke[fx] += ranke[fy];
}
else {
father[fx] = fy;
ranke[fy] += ranke[fx];
}
}
if (cnt != V - 1) ans = -1;
return ans;
}
int main() {
//FILE *p = freopen("test.txt", "r", stdin);
int i, j;
while (scanf("%d%d", &N, &M) != EOF) {
Makeset(N);
memset(fb, 0, sizeof(fb));
int f, t, c;
for (i = 0; i < M; i++) {
scanf("%d%d%d", &f, &t, &c);
G[i] = Node(f, t, c);
}
/*int res = Kruskal(N, M);
for (i = 1; i <= N; i++) { //判断有几个集合
fb[Find(i)] = 1;
}
int num = 0;
for (i = 1; i <= N; i++) {
if (fb[i]) num++;
}
if (num == 1) printf("%d\n", res);
else printf("-1\n");*/
printf("%d\n", Kruskal(N, M));
}
return 0;
}