P2914 [USACO08OCT] Power Failure G

题目描述

一场猛烈的雷暴摧毁了农场电力网的一些电线!农夫约翰有一张所有 NNN 根电线杆的地图(2≤N≤10002 \le N \le 10002N1000),这些电线杆被方便地编号为 1…N1\ldots N1N,并位于整数平面坐标 (xi,yi)(x_i, y_i)(xi,yi) 上(−100000≤xi≤100000,−100000≤yi≤100000-100000 \le x_i \le 100000, -100000 \le y_i \le 100000100000xi100000,100000yi100000)。

WWW 根电线(1≤W≤100001 \le W \le 100001W10000)连接成对的电线杆 PiP_iPiPjP_jPj1≤Pi≤N,1≤Pj≤N1 \le P_i \le N, 1 \le P_j \le N1PiN,1PjN)。

他需要从电线杆 111 获取电力到电线杆 NNN(这意味着一些电线可以从电线杆 111 通过某些中间电线杆传输到电线杆 NNN)。

给定 NNN 根电线杆的位置和剩余电线的列表,确定恢复电力连接所需的最小电线长度,以便电力可以从电线杆 111 流向电线杆 NNN。没有电线可以长于某个实数 MMM0.0<M≤200000.00.0 < M \le 200000.00.0<M200000.0)。

例如,下面左侧是暴风雨后 999 根电线杆和 333 根电线的地图。对于这个任务,M=2.0M = 2.0M=2.0。最佳的电线连接方案是连接电线杆 444666,以及电线杆 666999

   暴风雨后                  最优重新连接
3  . . . 7 9 . . . . .          3  . . . 7 9 . . . . .
                                          /
2  . . 5 6 . . . . . .          2  . . 5 6 . . . . . .
                                        /
1  2-3-4 . 8 . . . . .          1  2-3-4 . 8 . . . . .
   |                               |
0  1 . . . . . . . . .          0  1 . . . . . . . . .

   0 1 2 3 4 5 6 7 8 9             0 1 2 3 4 5 6 7 8 9

总长度为 1.414213562+1.414213562=2.8284271241.414213562 + 1.414213562 = 2.8284271241.414213562+1.414213562=2.828427124

分值:350

输入格式

111 行:两个用空格分隔的整数:NNNWWW

222 行:一个实数:MMM

3…N+23\ldots N+23N+2 行:每行包含两个用空格分隔的整数:xix_ixiyiy_iyi

N+3…N+2+WN+3\ldots N+2+WN+3N+2+W 行:两个用空格分隔的整数:PiP_iPiPjP_jPj

输出格式

第 1 行:单独一行上的一个整数。如果无法恢复连接,输出 -1。否则,输出一个整数,该整数是恢复电力所需的总最小成本的 100010001000 倍。不要进行任何四舍五入;截断结果乘积。

输入输出样例 #1

输入 #1

9 3 
2.0 
0 0 
0 1 
1 1 
2 1 
2 2 
3 2 
3 3 
4 1 
4 3 
1 2 
2 3 
3 4 

输出 #1

2828 

说明/提示

就像上面的图示一样。

如上所述。
(由 ChatGPT 4o 翻译)

C++实现

#include <bits/stdc++.h>
using namespace std;
int n, w;
double m, d[1001];
bool v[1001];
double a[1001][1001];
struct rec {
	double x, y;
} p[1001];
int main() {
	cin >> n >> w >> m;
	for (register int i = 1; i <= n; ++i) scanf("%lf%lf", &p[i].x, &p[i].y);
	for (register int i = 1; i <= n; ++i) 
		for (register int j = 1; j <= n; ++j) {
			a[i][j] = sqrt(pow(p[i].x - p[j].x, 2) + pow(p[i].y - p[j].y, 2));
			if (a[i][j] > m) a[i][j] = 1e18;
		}
	for (register int i = 1; i <= w; ++i) {
		int x, y;
		scanf("%d%d", &x, &y);
		a[y][x] = a[x][y] = 0;
	}
	priority_queue<pair<double, int> > q;
	for (register int i = 1; i <= n; ++i) d[i] = 1e18;
	q.push(make_pair(0.0, 1));
	memset(v, 0, sizeof v);
	d[1] = 0;
	while (q.size()) {
		int x = q.top().second;
		q.pop();
		if (v[x]) continue;
		v[x] = 1;
		for (register int i = 1; i <= n; ++i) {
			double z = a[x][i];
			if (z == 1e18) continue;
			if (d[i] > d[x] + z) {
				d[i] = d[x] + z;
				q.push(make_pair(-d[i], i));
			}
		}
	}
	if (d[n] == 1e18) puts("-1");
	else printf("%.0lf", floor(d[n] * 1000));
} 

在这里插入图片描述

后续

接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐