USACO 3.2.6 Sweet Butter 香甜的黄油(最短路)

Description

农夫John发现做出全威斯康辛州最甜的黄油的方法:糖。把糖放在一片牧场上,他知道N(1<=N<=500)只奶牛会过来舔它,这样就能做出能卖好价钱的超甜黄油。当然,他将付出额外的费用在奶牛上。 农夫John很狡猾。像以前的Pavlov,他知道他可以训练这些奶牛,让它们在听到铃声时去一个特定的牧场。他打算将糖放在那里然后下午发出铃声,以至他可以在晚上挤奶。 农夫John知道每只奶牛都在各自喜欢的牧场(一个牧场不一定只有一头牛)。给出各头牛在的牧场和牧场间的路线,找出使所有牛到达的路程和最短的牧场(他将把糖放在那)

Input

第一行: 三个数:奶牛数N,牧场数(2<=P<=800),牧场间道路数C(1<=C<=1450) 第二行到第N+1行: 1到N头奶牛所在的牧场号 第N+2行到第N+C+1行: 每行有三个数:相连的牧场A、B,两牧场间距离D(1<=D<=255),当然,连接是双向的

Output

一行 输出奶牛必须行走的最小的距离和

Sample Input

3 4 5
2
3
4
1 2 1
1 3 5
2 3 7
2 4 3
3 4 5
/*
{样例图形
          P2  
 P1 @--1--@ C1
         |
         | 
       5  7  3
         |   
         |     C3
       C2 @--5--@
          P3    P4
}
*/

Sample Output

8
/*{说明:
  放在4号牧场最优
}*/

解题思路:最短路问题,找到一个点,所有目标点到该点的距离之和最短。我最开始想用Floyd算法,我觉得最多不就是800个点,n^3应该不超时,但还是超时了,
对于这道题应该使用SPFA
算法,SPFA是求最短路的算法中时间复杂度最低的算法。
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <vector>
 5 #include <queue>
 6 #define inf 0x3f3f3f3f
 7 #define maxn 1500
 8 using namespace std;
 9 struct EDGE
10 {
11     int to;
12     int v;
13 } t;
14 vector<EDGE>e[maxn];
15 int n,m,z;
16 int a[maxn];
17 int vis[maxn];
18 int dis[maxn];
19 void add(int from,int to,int v)
20 {
21     t.to=to;
22     t.v=v;
23     e[from].push_back(t);
24 }
25 void SPFA(int s)
26 {
27     queue<int> q;
28     int i;
29     for(i=1;i<=n;i++)///每次调用的初始化
30     {
31         dis[i]=inf;
32         vis[i]=0;
33     }
34     q.push(s);
35     dis[s] = 0;
36     vis[s] = 1;
37     while(!q.empty())
38     {
39         int now=q.front();
40         q.pop();
41         vis[now]=0;///弹出队列,取消标志
42         for(i=0;i<e[now].size();i++)
43         {
44             if(dis[e[now][i].to]>dis[now]+e[now][i].v)
45             {
46                 dis[e[now][i].to]=dis[now]+e[now][i].v;
47                 if(!vis[e[now][i].to])///不在队列就加到队列中
48                 {
49                     vis[e[now][i].to]=1;
50                     q.push(e[now][i].to);
51                 }
52             }
53         }
54     }
55 }
56 int main()
57 {
58     int from,to,v,i,j,mins,ans;
59     scanf("%d%d%d",&z,&n,&m);
60     for(i=1; i<=z; i++)
61     {
62         scanf("%d",&a[i]);
63     }
64     mins=inf;
65     for(i=1; i<=m; i++)
66     {
67         scanf("%d%d%d",&from,&to,&v);
68         add(from,to,v);
69         add(to,from,v);
70     }
71     for(i=1; i<=n; i++)
72     {
73         ans=0;
74         SPFA(i);
75         for(j=1; j<=z; j++)
76         {
77             ans+=dis[a[j]];
78         }
79         if(ans<mins)///找最小和
80         {
81             mins=ans;
82         }
83     }
84     printf("%d
",mins);
85     return 0;
86 }



原文地址:https://www.cnblogs.com/wkfvawl/p/9705780.html