今日刷题:\(1015-1018\)
1015 NC24755 [USACO 2010 Dec S]Apple Delivery
题目描述
Bessie has two crisp red apples to deliver to two of her friends in the herd. Of course, she travels the \(C\) (\(1 <= C <= 200,000\)) cowpaths which are arranged as the usual graph which connects \(P\) (\(1 <= P <= 100,000\)) pastures conveniently numbered from \(1..P\): no cowpath leads from a pasture to itself, cowpaths are bidirectional, each cowpath has an associated distance, and, best of all, it is always possible to get from any pasture to any other pasture. Each cowpath connects two differing pastures \(P1_i\) (\(1 <= P1_i <= P\)) and \(P2_i\) (\(1 <= P2_i <= P\)) with a distance between them of \(D_i\). The sum of all the distances \(D_i\) does not exceed \(2,000,000,000\).
What is the minimum total distance Bessie must travel to deliver both apples by starting at pasture \(PB\) (\(1 <= PB <= P\)) and visiting pastures \(PA_1\) (\(1 <= PA_1 <= P\)) and \(PA_2\) (\(1 <= PA_2 <= P\)) in any order. All three of these pastures are distinct, of course.
输入描述
- Line \(1\): Line \(1\) contains five space-separated integers: \(C, P, PB, PA_1\) and \(PA_2\)
- Lines \(2..C+1\): Line \(i+1\) describes cowpath \(i\) by naming two pastures it connects and the distance between them: \(P1_i,P2_i,D_i\)
输出描述
- Line \(1\): The shortest distance Bessie must travel to deliver both apples
示例
输入
9 7 5 1 4
5 1 7
6 7 2
4 7 2
5 6 1
5 2 4
4 3 2
1 2 3
3 2 2
2 6 3
输出
12
解题思路
将苹果从 \(PB\) 送到 \(PA_1\) 和 \(PA_2\),求解最小的路径长度和。
最短路:经过顺序即 \(PB->PA_1->PA_2\) 和 \(PB->PA_2->PA_1\),求解相邻两点间的最短路加和,然后两种顺序求最小值即可。
C++ 代码
#include <bits/stdc++.h>
using namespace std;
const int N = 100010, M = 400010;
typedef long long LL;
typedef pair<LL, int> PLI;
int n, m, pb, pa1, pa2;
int h[N], e[M], ne[M], w[M], idx;
bool vis[N];
LL dist[N];
void add(int a, int b, int c) {
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
LL dijkstra(int st, int ed) {
priority_queue<PLI, vector<PLI>, greater<PLI>> pq;
memset(vis, 0, sizeof vis);
memset(dist, 0x3f, sizeof dist);
dist[st] = 0;
pq.push({dist[st], st});
while (pq.size()) {
auto t = pq.top();
pq.pop();
int ver = t.second;
if (ver == ed)
break;
if (vis[ver]) continue;
vis[ver] = true;
for (int i = h[ver]; ~i; i = ne[i]) {
int j = e[i];
if (dist[j] > dist[ver] + w[i]) {
dist[j] = dist[ver] + (LL) w[i];
pq.push({dist[j], j});
}
}
}
return dist[ed];
}
int main() {
memset(h, -1, sizeof h);
scanf("%d%d%d%d%d", &m, &n, &pb, &pa1, &pa2);
for (int i = 0; i < m; i++) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
add(b, a, c);
}
LL ans1 = dijkstra(pb, pa1) + dijkstra(pa1, pa2);
LL ans2 = dijkstra(pb, pa2) + dijkstra(pa2, pa1);
printf("%lld\n", min(ans1, ans2));
return 0;
}
1016 NC24370 [USACO 2012 Dec S]Milk Routing
题目描述
Farmer John's farm has an outdated network of \(M\) pipes (\(1 <= M <= 500\)) for pumping milk from the barn to his milk storage tank. He wants to remove and update most of these over the next year, but he wants to leave exactly one path worth of pipes intact, so that he can still pump milk from the barn to the storage tank.
The pipe network is described by \(N\) junction points (\(1 <= N <= 500\)), each of which can serve as the endpoint of a set of pipes. Junction point \(1\) is the barn, and junction point \(N\) is the storage tank. Each of the \(M\) bi-directional pipes runs between a pair of junction points, and has an associated latency (the amount of time it takes milk to reach one end of the pipe from the other) and capacity (the amount of milk per unit time that can be pumped through the pipe in steady state). Multiple pipes can connect between the same pair of junction points.
For a path of pipes connecting from the barn to the tank, the latency of the path is the sum of the latencies of the pipes along the path, and the capacity of the path is the minimum of the capacities of the pipes along the path (since this is the "bottleneck" constraining the overall rate at which milk can be pumped through the path). If FJ wants to send a total of \(X\) units of milk through a path of pipes with latency \(L\) and capacity \(C\), the time this takes is therefore \(L + X/C\).
Given the structure of FJ's pipe network, please help him select a single path from the barn to the storage tank that will allow him to pump X units of milk in a minimum amount of total time.
输入描述
- Line \(1\): Three space-separated integers: \(N\, M\, X\) (\(1 <= X <= 1,000,000\)).
- Lines \(2..1+M\): Each line describes a pipe using \(4\) integers: \(I\, J\, L\, C\).
\(I\) and \(J\) (\(1 <= I,J <= N\)) are the junction points at both ends of the pipe. \(L\) and \(C\) (\(1 <= L,C <= 1,000,000\)) give the latency and capacity of the pipe.
输出描述
- Line \(1\): The minimum amount of time it will take FJ to send milk along a single path, rounded down to the nearest integer.
示例
输入
3 3 15
1 2 10 3
3 2 10 2
1 3 14 1
输出
27
说明
INPUT DETAILS:
FJ wants to send \(15\) units of milk through his pipe network. Pipe \(1\) connects junction point \(1\) (the barn) to junction point \(2\), and has a latency of \(10\) and a capacity of \(3\). Pipes \(2\) and \(3\) are similarly defined.
OUTPUT DETAILS:
The path \(1->3\) takes \(14 + 15/1 = 29\) units of time. The path \(1->2->3\) takes \(20 + 15/2 = 27.5\) units of time, and is therefore optimal.
解题思路
从两点间的延时为 \(L\),其管道限制为 \(C\)。求解从 \(1\) 到 \(n\) 的最少延时 \(\sum_iL_i+\frac{X}{minC_i}\),限制取该路径所有管道的最小值。
可以枚举管道限制,对于小于限制的边舍弃,然后求解最短路。
C++ 代码
#include <bits/stdc++.h>
using namespace std;
const int N = 510, M = 1010;
typedef pair<int, int> PII;
int n, m, X;
int h[N], e[M], ne[M], w[M], v[M], idx;
int dist[N], st[N];
void add(int a, int b, int c, int d) {
e[idx] = b, w[idx] = c, v[idx] = d, ne[idx] = h[a], h[a] = idx++;
}
void dijkstra(int c) {
memset(st, 0, sizeof st);
memset(dist, 0x3f, sizeof dist);
priority_queue<PII, vector<PII>, greater<PII>> pq;
dist[1] = 0;
pq.push({dist[1], 1});
while (pq.size()) {
auto t = pq.top();
pq.pop();
int ver = t.second;
if (st[ver]) continue;
st[ver] = true;
for (int i = h[ver]; ~i; i = ne[i]) {
if (v[i] < c) continue;
int j = e[i];
if (dist[j] > dist[ver] + w[i]) {
dist[j] = dist[ver] + w[i];
pq.push({dist[j], j});
}
}
}
// printf("%d\n", dist[n]);
}
int main() {
memset(h, -1, sizeof h);
scanf("%d%d%d", &n, &m, &X);
int C = 0;
for (int i = 0; i < m; i++) {
int a, b, c, d;
scanf("%d%d%d%d", &a, &b, &c, &d);
add(a, b, c, d);
add(b, a, c, d);
C = max(C, d);
}
// cout << C << endl;
int ans = 2e9;
for (int c = C; c >= 1; c--) {
dijkstra(c);
ans = min(ans, dist[n] + X / c);
}
printf("%d\n", ans);
return 0;
}
1017 NC25077 [USACO 2007 Ope B]Bronze Cow Party
题目描述
One cow from each of \(N\) farms (\(1 <= N <= 1000\)) conveniently numbered \(1..N\) is attending the big cow party to be held at farm \(X\) (\(1 <= X <= N\)). Each of \(M\) (\(1 <= M <= 100,000\)) bidirectional roads connects one farm to another. It is always possible to travel from one farm to another on the roads. Traversing road \(i\) requires \(T_i\) (\(1 <= T_i <= 100\)) units of time. One or more pairs of farms might be directly connected by more than one road.
After all the cows gathered at farm \(X\), they realized that every single cow left her party favors back at the farm. They decided to suspend the party and send all the cows back to get the party favors. The cows all travel optimal routes to their home farm and back to the party. What is the minimum number of time units the party must be suspended?
输入描述
Line \(1\): Three space-separated integers, respectively: \(N, M\), and \(X\)
Lines \(2..M+1\): Line \(i+1\) describes road \(i\) with three space-separated integers, respectively: \(A_i, B_i\), and \(T_i\). The described road connects \(A_i\) and \(B_i\) and requires \(T_i\) time units to traverse.
输出描述
Line \(1\): One integer: the minimum amount of time the party must be suspended.
示例
输入
4 8 2
1 2 7
1 3 8
1 4 4
2 1 3
2 3 1
3 1 2
3 4 6
4 2 2
输出
6
说明
Four cows; eight roads; party at farm \(2\).
Direct paths connects farm \(2\) to each of the other farms (to farm \(1\): \(7\) and \(3\); to farm \(3\): \(1\); to farm \(4\): \(2\)). The longest path is length \(3\), so the round-trip time is \(6\).
解题思路
题意为所有牛都会从 \(X\) 点回到其余各点,牛会按照耗时最短的路通过,问最长的往返时间。
最短路。以 \(X\) 为起点求出到其余各点的最短路,然后找出最大值乘以二。
C++ 代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1010, M = 200010;
typedef pair<int, int> PII;
int n, m, X;
int h[N], e[M], ne[M], w[M], idx;
int dist[N], st[N];
void add(int a, int b, int c) {
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
void dijkstra(int s) {
memset(st, 0, sizeof st);
memset(dist, 0x3f, sizeof dist);
priority_queue<PII, vector<PII>, greater<PII>> pq;
dist[s] = 0;
pq.push({dist[s], s});
while (pq.size()) {
auto t = pq.top();
pq.pop();
int ver = t.second;
if (st[ver]) continue;
st[ver] = true;
for (int i = h[ver]; ~i; i = ne[i]) {
int j = e[i];
if (dist[j] > dist[ver] + w[i]) {
dist[j] = dist[ver] + w[i];
pq.push({dist[j], j});
}
}
}
}
int main() {
memset(h, -1, sizeof h);
scanf("%d%d%d", &n, &m, &X);
for (int i = 0; i < m; i++) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
add(b, a, c);
}
dijkstra(X);
int ans = 0;
for (int i = 1; i <= n; i++)
ans = max(ans, dist[i]);
printf("%d\n", ans * 2);
return 0;
}
1018 NC25005 [USACO 2008 Ope S]Clear And Present Danger
题目描述
Farmer John is on a boat seeking fabled treasure on one of the \(N\) (\(1 <= N <= 100\)) islands conveniently labeled \(1..N\) in the Cowribbean Sea.
The treasure map tells him that he must travel through a certain sequence \(A_1, A_2, ..., A_M\) of \(M\) (\(2 <= M <= 10,000\)) islands, starting on island \(1\) and ending on island \(N\) before the treasure will appear to him. He can visit these and other islands out of order and even more than once, but his trip must include the Ai sequence in the order specified by the map.
FJ wants to avoid pirates and knows the pirate-danger rating (\(0 <= danger <= 100,000\)) between each pair of islands. The total danger rating of his mission is the sum of the danger ratings of all the paths he traverses.
Help Farmer John find the least dangerous route to the treasure that satisfies the treasure map's requirement.
输入描述
- Line \(1\): Two space-separated integers: \(N\) and \(M\)
- Lines \(2\)..\(M+1\): Line \(i+1\) describes the \(i\)-th island FJ must visit with a single integer: \(A_i\)
- Lines \(M+2\)..\(N+M+1\): Line \(i+M+1\) contains \(N\) space-separated integers that are the respective danger rating of the path between island \(i\) and islands \(1, 2,\) ..., and \(N\), respectively. The ith integer is always zero.
输出描述
- Line \(1\): The minimum danger that Farmer John can encounter while obtaining the treasure.
示例
输入
3 4
1
2
1
3
0 5 1
5 0 2
1 2 0
输出
7
说明
There are \(3\) islands and the treasure map requires Farmer John to visit a sequence of \(4\) islands in order: island \(1\), island \(2\), island \(1\) again, and finally island \(3\). The danger ratings of the paths are given: the paths \((1, 2)\); \((2, 3)\); \((3, 1)\) and the reverse paths have danger ratings of \(5\), \(2\), and \(1\), respectively.
He can get the treasure with a total danger of \(7\) by traveling in the sequence of islands \(1, 3, 2, 3, 1\), and \(3\). The cow map's requirement (\(1, 2, 1\), and \(3\)) is satisfied by this route. We avoid the path between islands \(1\) and \(2\) because it has a large danger rating.
解题思路
题意是求解按照顺序遍历的最短路径。
最短路,按照序列顺序,相邻两个为起点和终点,求出最短路,最后加和。如果遍历序列,每次都求解一次的话,时间复杂度为 \(O(N^2·M)\),大概为 \(10^8\)。可以预处理,枚举所有点为起点,求解一次该点到其他点的最短路,则时间复杂度为 \(O(N^3)\)。
最短路的求解使用 \(Dijkstra\) 算法。
C++ 代码
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
typedef pair<int, int> PII;
int n, m;
int g[N][N], dist[N][N];
bool st[N];
void dijkstra(int s) {
memset(dist[s], 0x3f, sizeof dist[s]);
memset(st, 0, sizeof st);
dist[s][s] = 0;
for (int i = 0; i < n - 1; i++) {
int t = -1;
for (int j = 1; j <= n; j++) {
if (!st[j] && (t == -1 || dist[s][t] > dist[s][j]))
t = j;
}
for (int j = 1; j <= n; j++) {
dist[s][j] = min(dist[s][t] + g[t][j], dist[s][j]);
}
st[t] = true;
}
}
int main() {
scanf("%d%d", &n, &m);
vector<int> seq;
for (int i = 0; i < m; i++) {
int a;
scanf("%d", &a);
seq.push_back(a);
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
scanf("%d", &g[i][j]);
int ans = 0;
for (int i = 1; i <= n; i++)
dijkstra(i);
for (int i = 0; i + 1 < seq.size(); i++) {
ans += dist[seq[i]][seq[i + 1]];
}
printf("%d\n", ans);
return 0;
}
本文来自博客园,作者:Cocoicobird,转载请注明原文链接:https://www.cnblogs.com/Cocoicobird/p/19733806
浙公网安备 33010602011771号