P1045 Kerry 的电缆网络(Kruskal+并查集)



描述

Kerry 是德国的一位电缆商人。因联合国脱贫计划的邀请,他准备负责在土鲁齐亚埃萨亚克斯乌托斯邦建立电缆网络,以满足这个国家的用电需求。当然,现在土鲁齐亚埃萨亚克斯乌托斯邦没有任何电缆。已知土鲁齐亚埃萨亚克斯乌托斯邦一共有n个城镇,已经编号为1到n。其中任意两个城镇可能有一条路,也可能没有。如果两个城镇之间有一条路pi,那么这条路有一个长度si,则Kerry可以在这两个城市之间建立一条电缆线,电缆线的长度也就是这条路的长度si。

现在Kerry准备了s长的电缆线,电缆线可以任意拆断,拆断不损失任何电缆线。他需要将土鲁齐亚埃萨亚克斯乌托斯邦所有城镇都能够连入这个电缆网络。那么,Kenny能不能使用这s长度的电缆线完成这项工作;如果能够完成,那么Kerry最少耗用多少长度的电缆线呢?

格式

输入格式

第一行一个正实数S;
第二行一个正整数n;
接下来一共有m行,第i行有两个整数xi,yi和一个实数si,表示编号为xi个村庄和编号为yi个村庄之间有一条路,路的长度为si。

输入保证xi不等于yi,两个城镇之间不会有两条路。

输出格式

若能够完成(建立这样的电缆网络),则输出(其中<X>代表最少的电缆线长度,保留两位小数):
Need <X> miles of cable
否则输出:
Impossible

样例

样例输入

100.0
4
1 2 2.0
1 3 4.2
1 4 6.7
3 4 4.0
2 4 10.0

样例输出

Need 10.20 miles of cable
并查集+Kruskal(未优化版,但是可AC)
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

struct Kruskal
{
    int x;
    int y;
    double value;
};

int father[100002], son[100002];

bool cmp(const Kruskal &a, const Kruskal& b)
{
    return a.value < b.value;
}

int unionsearch(int x)
{
    if (x == father[x])
        return x;
    else
        return unionsearch(father[x]); //有改进余地
}

bool join(int x, int y)
{
    int root1 = unionsearch(x);
    int root2 = unionsearch(y);
    if (root1 == root2)
        return false;
    if (son[root1] >= son[root2])
    {
        father[root2] = root1;
        son[root1] +=son[root2];
    }
    else
    {
        father[root1] = root2;
        son[root2] += son[root1];
    }
    return true;
}

int main()
{
    freopen("in.txt", "r", stdin);

    double total = 0;
    double sum = 0;
    int n, m, flag = 0, num = 0;
    Kruskal edge[100002];
    scanf("%lf", &total);
    scanf("%d", &n);
    m = 1;
    while(3 == scanf("%d%d%lf", &edge[m].x, &edge[m].y, &edge[m].value))
        m++;
    m--;
    for(int i = 1; i <= n; i++)
    {
        father[i] = i;
        son[i] = 1;
    }
    sort(edge+1, edge+m+1, cmp);
    for (int i = 1; i <= m; i++)
    {
        if(join(edge[i].x, edge[i].y))
        {
            num++;  //edge number
            sum += edge[i].value;
        }
        if(num == n-1)
        {
            flag = 1;
            break;
        }
    }
    if (sum > total)
        flag = 0;
    if (flag)
        printf("Need %.2lf miles of cable\n", sum);
    else
        printf("Impossible\n");

    fclose(stdin);
    return 0;
}

Prim朴素算法肯定不行,kruskal+并查集的走起

版权声明:本文为i641015077原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。