洛谷 P2212 [USACO14MAR]浇地Watering the Fields
题目描述
农民约翰想建立一个灌溉系统,给他的NN (1 <= NN <= 2000)块田送水。农田在一个二维平面上,第i块农田坐标为(x_ixi , y_iyi )(0 <= x_ixi , y_iyi <= 1000),在农田ii 和农田jj 自己铺设水管的费用是这两块农田的欧几里得距离的平方(x_i - x_j)^2 + (y_i - y_j)^2(xi−xj)2+(yi−yj)2 。
农民约翰希望所有的农田之间都能通水,而且希望花费最少的钱。但是安装工人拒绝安装费用小于C的水管(1 <= CC <= 1,000,000)。
请帮助农民约翰建立一个花费最小的灌溉网络,如果无法建立请输出-1。
输入输出格式
输入格式:
* Line 1: The integers N and C.
* Lines 2..1+N: Line i+1 contains the integers xi and yi.
输出格式:
* Line 1: The minimum cost of a network of pipes connecting the
fields, or -1 if no such network can be built.
输入输出样例
说明
输入信息:
在地点(0,2),(5,0)和(4,3)有3个字段。 承包商
将只安装成本至少为11的管道。
输出细节:
自从(4,3)和(5,0)以来,FJ不能在字段之间建立管道
成本将只有10元。他因此在(0,2)和(5,0)之间建立一条管道,
成本为29,管道为(0.2)至(4,3),成本为17。
来源:USACO 2014年3月比赛,银牌
考察算法:生成树 难度:普及+/提高
思路:通过每个点的横、纵坐标,求出每两点间的距离 暂且按O(n^2)来算
判断计算出的距离是否小于题目中的C,然后建边
然后就是简单地最小生成树啦啦啦
#include<algorithm> #include<cstdio> #define N 2005 using namespace std; int n, m, tot, sum; int fa[N]; int xx[N], yy[N]; struct nond { int l, r; int s; }e[N*(N-1)]; //注意数组不要开得太小,会RE的(比如我)qwq int find(int x) { if(fa[x]==x) return x; else return fa[x] = find(fa[x]); } bool cmp(nond x, nond y) { return x.s < y.s; } int main() { int k = 0; scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) fa[i] = i; for(int i = 1; i <= n; i++) scanf("%d%d", &xx[i], &yy[i]); for(int i = 1; i <= n; i++) for(int j = i+1; j <= n; j++) { int tmp = (xx[i]-xx[j])*(xx[i]-xx[j]) + (yy[i]-yy[j])*(yy[i]-yy[j]); //求出每两点间的距离 if(tmp >= m) e[++k].l = i, e[k].r = j, e[k].s = tmp; //判断是否建边 } sort(e+1, e+k+1, cmp); for(int i = 1; i <= k; i++) { int x = find(e[i].l), y = find(e[i].r); if(x == y) continue; fa[x] = y; tot++; sum += e[i].s; if(tot == n-1) break; //小小的优化 } if(tot < n-1) printf("-1"); //注意不要漏了输出 -1 else printf("%d", sum); return 0; }