Description
Kerry 是德国的一位电缆商人。因联合国脱贫计划的邀请,他准备负责在土鲁齐亚埃萨亚克斯乌托斯邦建立电缆网络,以满足这个国家的用电需求。当然,现在土鲁齐亚埃萨亚克斯乌托斯邦没有任何电缆。已知土鲁齐亚埃萨亚克斯乌托斯邦一共有n个城镇,已经编号为1到n。其中任意两个城镇可能有一条路,也可能没有。如果两个城镇之间有一条路pi,那么这条路有一个长度si,则Kerry可以在这两个城市之间建立一条电缆线,电缆线的长度也就是这条路的长度si。
现在Kerry准备了s长的电缆线,电缆线可以任意拆断,拆断不损失任何电缆线。他需要将土鲁齐亚埃萨亚克斯乌托斯邦所有城镇都能够连入这个电缆网络。那么,Kenny能不能使用这s长度的电缆线完成这项工作;如果能够完成,那么Kerry最少耗用多少长度的电缆线呢?
Input
第一行一个正实数S;
第二行一个正整数n;
接下来一共有m行(m是个未知数),第i行有两个整数xi,yi和一个实数si,表示编号为xi个村庄和编号为yi个村庄之间有一条路,路的长度为si。
输入保证xi不等于yi,两个城镇之间不会有两条路。
Output
若能够完成(建立这样的电缆网络),则输出(其中代表最少的电缆线长度,保留两位小数):
Needmiles of cable
否则输出:
Impossible
Sample Input
100.0
4
1 2 2.0
1 3 4.2
1 4 6.7
3 4 4.0
2 4 10.0
Sample Output
Need 10.20 miles of cable
HINT
【注释 Hint 】
1<=n,m<=100000
第一次开float,结果玄学WA,发现原来是精度的问题,开double就A了。
#include <iostream>
#include <vector>
#include <algorithm>
#define SIZE 100001
using namespace std;
struct edge
{
int from, to;
double dis;
};
vector<edge> graph;
int pre[SIZE]; // 前驱
bool comp(edge a, edge b)
{
return a.dis < b.dis;
}
int find(int x) // 找祖先
{
return (pre[x]) ? pre[x] = find(pre[x]) : x;
}
int main(int argc, char** argv)
{
int n, u, v, c = 1, i, prex, prey;
double s, w, res = 0;
scanf("%lf%d", &s, &n);
while (~scanf("%d%d%lf", &u, &v, &w))
{
graph.push_back({u, v, w});
}
sort(graph.begin(), graph.end(), comp);
for (i = 0; i < graph.size(); ++i) // 求最小生成树
{
u = graph[i].from;
v = graph[i].to;
w = graph[i].dis;
prex = find(u);
prey = find(v);
if (prex ^ prey)
{
res += w;
if ((++c == n) || (res > s))
{
break;
}
pre[prex] = prey;
}
}
if ((c == n) && (res <= s))
{
printf("Need %.2f miles of cable", res);
}
else
{
printf("Impossible");
}
return 0;
}