题目链接:https://syzoj.com/problem/291
内存限制:128 MiB 时间限制:1000 ms
题目描述
农夫John发现做出全威斯康辛州最甜的黄油的方法:糖。把糖放在一片牧场上,他知道N(1<=N<=500)只奶牛会过来舔它,这样就能做出能卖好价钱的超甜黄油。当然,他将付出额外的费用在奶牛上。 农夫John很狡猾。像以前的巴甫洛夫,他知道他可以训练这些奶牛,让它们在听到铃声时去一个特定的牧场。他打算将糖放在那里然后下午发出铃声,以至他可以在晚上挤奶。 农夫John知道每只奶牛都在各自喜欢的牧场(一个牧场不一定只有一头牛)。给出各头牛在的牧场和牧场间的路线,找出使所有牛到达的路程和最短的牧场(他将把糖放在那)。
输入格式
第一行: 三个数:奶牛数N,牧场数P(2<=P<=800),牧场间道路数C(1<=C<=1450)。 第二行到第N+1行: 1到N头奶牛所在的牧场号。 第N+2行到第N+C+1行:每行有三个数:相连的牧场A、B,两牧场间距(1<=D<=255),当然,连接是双向的。
输出格式
一行 输出奶牛必须行走的最小的距离和.
样例输入
3 4 5
2
3
4
1 2 1
1 3 5
2 3 7
2 4 3
3 4 5
样例输出
8
提示
样例图形
P2
P1 @--1--@ C1
\ |\
\ | \
5 7 3
\ | \
\| \ C3
C2 @--5--@
P3 P4//说明:放在4号牧场最优
解题思路
先算出牧场两两之间的最短路径,然后枚举每个牧场到其它牧场的距离相加,求出最小值。
#include <bits/stdc++.h>
using namespace std;
struct edge {
int u, v, w;
}e[2905];
int cnt, s[805], f[805], vis[805], dis[805];
void Add(int u, int v, int w) {
e[++cnt] = (edge){f[u], v, w};
f[u] = cnt;
}
void Spfa(int s) {
queue <int> Q;
Q.push(s);
dis[s] = 0;
vis[s] = 1;
while (!Q.empty()) {
int t = Q.front();
Q.pop();
vis[t] = 0;
for (int i = f[t]; i; i = e[i].u) {
int v = e[i].v;
if (dis[v] > dis[t] + e[i].w) {
dis[v] = dis[t] + e[i].w;
if (!vis[v]) {
Q.push(v);
vis[v] = 1;
}
}
}
}
}
int main() {
int n, m, p, u, v, w, ans, min_s;
while (~scanf("%d%d%d", &n, &m, &p)) {
cnt = 0;
min_s = 0x3f3f3f3f;
memset(f, 0, sizeof(f));
for (int i = 1; i <= n; i++)
scanf("%d", &s[i]);
for (int i = 0; i < p; i++) {
scanf("%d%d%d", &u, &v, &w);
Add(u, v, w);
Add(v, u, w);
}
for (int i = 1; i <= m; i++) {
memset(vis, 0, sizeof(vis));
memset(dis, 0x3f, sizeof(dis));
Spfa(i);
ans = 0;
for (int j = 1; j <= n; j++)
ans += dis[s[j]];
min_s = min(ans, min_s);
}
printf("%d\n", min_s);
}
return 0;
}