USACO 2007 December Contest, Silver Problem 2. Building Roads Kruskal最小生成树算法

PROBLEM:

(ENGLISH VERSION)

Farmer John had just acquired several new farms! He wants to connect the farms with roads so that he can travel from any farm to any other farm via a sequence of roads; roads already connect some of the farms.

Each of the N (1 ≤ N ≤ 1,000) farms (conveniently numbered 1..N) is represented by a position (Xi, Yi) on the plane (0 ≤ Xi ≤ 1,000,000; 0 ≤ Yi ≤ 1,000,000). Given the preexisting M roads (1 ≤ M ≤ 1,000) as pairs of connected farms, help Farmer John determine the smallest length of additional roads he must build to connect all his farms.

INPUT FORMAT:

Line 1: Two space-separated integers: N and M

Lines 2..N+1: Two space-separated integers: Xi and Yi

Lines N+2..N+M+2: Two space-separated integers: i and j, indicating that there is already a road connecting the farm i and farm j.

OUTPUT FORMAT:

Line 1: Smallest length of additional roads required to connect all farms, printed without rounding to two decimal places. Be sure to calculate distances as 64-bit floating point numbers.

SAMPLE INPUT

4 1
1 1
3 1
2 3
4 3
1 4

SAMPLE OUTPUT

4.00

USACO ANALYSIS

USACO DEC07 Problem ‘roads‘ Analysis

by Richard Peng

We note that since all edges have non-negative weights, there will not be a cycle in the final version of the graph. Thus, this problem is equivalent to finding the minimum spanning tree in a graph where the edge weights are the Euclidean distances (with the exception of a few whose distances are set to zero).

Several minimum spanning tree algorithms can be use here. Since we‘re finding the MST of a dense graph, the best option is probably the O(n^2) version of the Prim algorithm:

  • Start with the tree being a single vertex
  • Keep a list of distances of every other vertex to the tree
  • At each iteration
    • Add the closest vertex to the tree
    • Update the distances accordingly.

This runs in O(n^2) time, which suffices for this problem.

By the way: This problem can actually be done in O(nlogn+m) time. The idea is basically the edges that could potentially be in the minimum spanning tree must belong to what‘s known as the Delaunay triangulation, which has O(n) edges. We can find the Delaunary triangulation in O(nlogn) time and apply a fast version of Kruskal‘s algorithm for sparse graphs to get the desired runtime.

程序

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int MAX = 1000 + 1;
 4 struct node
 5 {
 6     int From, Aim;
 7     long double Weight;
 8 }Edge[MAX*MAX];
 9 bool have[MAX][MAX];
10 int n,m,x[MAX],y[MAX],Count = 0,father[MAX];
11 long double ans = 0;
12 long double EdgeLength(int pointA, int pointB)
13 {
14     long long DiffX=x[pointA]-x[pointB], DiffY=y[pointA]-y[pointB];
15     return (long double)sqrt(DiffX*DiffX+DiffY*DiffY);
16 }
17 bool comp(node a, node b)
18 {
19     return a.Weight < b.Weight;
20 }
21 int find(int i)
22 {
23     if(father[i]==i)
24         return i;
25     return father[i]=find(father[i]);
26 }
27 void join(int a,int b)
28 {
29     if(find(a)==find(b))
30         return;
31     father[find(a)]=b;
32 }
33 int main()
34 {
35     //Kruskal + Disjoint-set
36     memset(have,0,sizeof(have));
37     cin >> n >> m;
38     for (int i = 1; i <= n; i++)
39         cin >> x[i] >> y[i], father[i] = i;
40     int a,b;
41     for (int i = 1; i <= m; i++)
42     {
43         cin >> a >> b;
44         have[a][b] = have[b][a] = true;
45         Edge[++Count] = (node){a,b,0};
46     }
47     for(int i = 1; i <= n; i++)
48         for(int j = i+1; j <= n; j++)
49             if(!have[i][j])
50                 Edge[++Count] = (node){i,j,EdgeLength(i,j)};
51     sort(Edge+1, Edge+(Count+1), comp);
52     //Disjoint-set
53     for(int i = 1; i <= Count; i++)
54         if(find(Edge[i].From) != find(Edge[i].Aim))
55         {
56             join(Edge[i].From, Edge[i].Aim);
57             ans += Edge[i].Weight;
58         }
59     printf("%.2Lf",ans);
60     return 0;
61 }

分析

本题的卡点就是已经存在的边为什么权重要设为0。简单来说,这条路已经存在相当于建造这条路的花费为0。(代码中红色的0)

其余的就没有什么难度了,简单套用Kruskal模板。

把所有点的连线及其长度存在数组Edge中,用一个变量Count计数。结构体node中From是边的一端,另一端是Aim。这条边的权重,也就是平面直角坐标系中用两点间距离公式求出的长度(请参见初中课本xd)。Kruskal的核心就是进行排序,按照权重大小进行排序。最后按照权重从小到大选边,只要不会产生环,就选择这条边。放到并查集中,就是它们拥有不同的爸爸祖先,就选择这条边。然后累加Weight权重。

时间: 2024-10-29 02:35:11

USACO 2007 December Contest, Silver Problem 2. Building Roads Kruskal最小生成树算法的相关文章

USACO 2014 US Open, Silver Problem 2. Dueling GPSs

Description Farmer John has recently purchased a new car online, but in his haste he accidentally clicked the "Submit" button twice when selecting extra features for the car, and as a result the car ended up equipped with two GPS navigation syst

USACO 2018 December Contest Platinum T2: Sort It Out

题目大意 FJ有 N(1≤N≤1e5 )头奶牛(分别用 1…N 编号)排成一行.FJ喜欢他的奶牛以升序排列,不幸的是现在她们的顺序被打乱了.在过去FJ曾经使用一些诸如“冒泡排序”的开创性的算法来使他的奶牛排好序,但今天他想偷个懒.取而代之,他会每次对着一头奶牛叫道“按顺序排好”.当一头奶牛被叫到的时候,她会确保自己在队伍中的顺序是正确的(从她的角度看来).当有一头紧接在她右边的奶牛的编号比她小,她们就交换位置.然后,当有一头紧接在她左边的奶牛的编号比她大,她们就交换位置.这样这头奶牛就完成了“按

USACO 2016 December Contest Gold T1: Moocast

题目大意 FJ的N头牛(1≤N≤1000)为了在他们之间传播信息, 想要组织一个"哞哞广播"系统. 奶牛们决定去用步话机装备自己而不是在很远的距离之外互相哞哞叫, 所以每一头奶牛都必须有一个步话机. 这些步话机都有一个限制传播半径, 但是奶牛们可以间接地通过中间奶牛传播信息, 所以并不是每头牛都必须直接向其他每一头奶牛连边. 奶牛们需要去决定多少钱花在步话机上, 如果他们花了$X, 那么他们都将会得到sqrt(x)距离的步话机. 所以, 两头牛之间的欧几里得距离平方最多是X. 请帮助奶

USACO 2016 December Contest Gold T3: Lasers and Mirrors

题目大意 出于某种原因,农夫约翰的牛总是在举行激光表演. 对于他们的最新展会,奶牛已经购买了一个大功率的激光器 - 这么大,事实上,他们似乎不能轻易地从它交付的位置移动.他们想以某种方式将激光的光发送到FJ物业另一侧的谷仓.激光器和谷仓都可以被认为位于FJ农场的地图上的2D平面中的点上.牛计划指挥激光器,使得它发出水平或竖直(即,与x或y轴平行)的光束.他们会将这个光束从一些镜子反射回去,直接到谷仓. 在农场上有N个栅栏(1≤N≤100,000),位于不同的二维点(也不同于激光和谷仓),牛可以安

USACO 2017 December Contest Gold T1: A Pie for a Pie

题目大意 Bessie和Elsie各自烤了 N(1≤N≤10^5)个馅饼.Bessie 会这 2N 个馅饼打分,Elsie 也会.二者的打分均为一个 ≤1e9 的非负整数.由于她们口味不同,每个派的两个分数可能不同.她们想互赠礼物.开始时,Bessie 送给 Elsie 一个馅饼.她们收到礼物(对方做的馅饼)后都会回赠对方一个自己做的馅饼.她们选择回礼的方法相同.以 Elsie 为例,Elsie 根据自己的打分来选择回礼.回礼的分数至少要大于她收到的馅饼的分数,但两个馅饼的分数差不能大于 D(0

USACO 2017 December Contest Platinum T2: Push a Box

题目大意 一个谷仓是一个N*M的矩形网格,有一些网格里有干草.Bessie站在其中一个格子内,还有一个格子里有一个大木箱.Bessie不能和大木箱在一个格子里,也不能和干草在一个格子里. 如果她不与干草一个格子,她就可以往自己旁边的四个方向(东西南北)移动,如果她想移动到有木箱的格子里,那个木箱就会被她推一格(只要木箱的那个方向还有空间),如果没有空间,那Bessie就不能移动了. 给你谷仓的布局(空格子,干草以及木箱位置)以及Bessie的出发位置和箱子要被推到的位置,请你帮忙计算Bessie

USACO 2017 December Contest Platinum T3: Greedy Gift Takers

题目大意 有 N(1≤N≤1e5)头牛按顺序排成一列,编号从 1 到 N,1 号牛在队头,N 号牛在队尾. 每次位于队头的牛 i 拿到一个礼物,然后插入到从队尾数ci?头牛之前的位置..举个栗子: 初始队列 1,2,3,4,5 c1?= 2,c2? = 3,则第一次操作后的序列为 2,3,1,4,5,第二次操作后的序列为 3,2,1,4,5.重复无限次操作,求最后有几头牛拿不到礼物. 题目分析 一上来有个显然的结论,若一个人得不到礼物那么原序列中在他后面的人肯定也得不到礼物,因为后面的人跳不到前

POJ3625 Building Roads

Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10803   Accepted: 3062 Description Farmer John had just acquired several new farms! He wants to connect the farms with roads so that he can travel from any farm to any other farm via a sequ

bzoj1626 / P2872 [USACO07DEC]道路建设Building Roads

P2872 [USACO07DEC]道路建设Building Roads kruskal求最小生成树. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<queue> 6 #include<algorithm> 7 #define re register 8 using namespace std; 9 ty