原题链接:https://www.luogu.org/problem/show?pid=1828#sub
经典的最短路问题。
各位不要被题目条件迷惑了,牧场想象成点,道路想象成边,奶牛所在的位置想象成点权就好。
输入的是无向图,所以在正向连边时反向连边。然后我们枚举所有的牧场,以枚举到的牧场作为起点寻求最短路,记录好dis数组。
算出最短路径后我们再枚举所有奶牛,开一个变量nowans记录以当前牧场为集合地点的所有牛需要走的最短路径,便有nowans += dis[c[j]] (j枚举自1到奶牛数)。
然后维护一下ans,输出就好了。
其实这题如果数据量较小的话可以用floyed求最短路。
参考代码:
1 #include <iostream> 2 #include <cstring> 3 #include <queue> 4 #include <cstdio> 5 #define maxn 23333 6 #define INF 2147483647 7 using namespace std; 8 struct Edge{ 9 int from,to,dis; 10 }; 11 Edge edge[maxn]; 12 int head[maxn]; 13 int dis[maxn]; 14 int u,v,d,tot = 0; 15 bool inq[maxn]; 16 int c[maxn]; 17 int N,P,C; 18 int ans = INF; 19 int nowans; 20 void add_edge(int from,int to,int dis){ 21 edge[++tot].from = head[from]; 22 edge[tot].to = to; 23 edge[tot].dis = dis; 24 head[from] = tot; 25 } 26 27 void spfa(int s){ 28 memset(inq,false,sizeof(inq)); 29 for (int i=1;i<=P;i++) 30 dis[i] = INF; 31 dis[s] = 0; 32 queue<int> q; 33 q.push(s); 34 inq[s] = true; 35 while (!q.empty()){ 36 int u = q.front(); 37 q.pop(); 38 inq[u] = false; 39 for (int i = head[u];i!=0;i=edge[i].from){ 40 int v = edge[i].to; 41 int w = edge[i].dis; 42 if (dis[u] + w < dis[v]){ 43 dis[v] = w + dis[u]; 44 if (!inq[v]){ 45 inq[v] = true; 46 q.push(v); 47 } 48 } 49 } 50 } 51 } 52 53 int main(){ 54 cin >> N >> P >> C; 55 for (int i=1;i<=N;i++) 56 cin >> c[i]; 57 for (int i=1;i<=C;i++){ 58 cin >> u >> v >> d; 59 add_edge(u,v,d); 60 add_edge(v,u,d); 61 } 62 for (int i=1;i<=P;i++){ 63 spfa(i); 64 nowans = 0; 65 for (int j=1;j<=N;j++) 66 nowans += dis[c[j]]; 67 ans = min(ans,nowans); 68 } 69 cout << ans << endl; 70 return 0; 71 }