WUST 1935 香甜的黄油(最短路径+SPFA算法)
2017-07-10 22:07
429 查看
1935: 香甜的黄油
Time Limit: 1 Sec Memory Limit: 128 MB 64bit IO Format: %lldSubmitted: 36 Accepted: 11
[Submit][Status][Web
Board]
Description
农夫John发现做出全威斯康辛州最甜的黄油的方法:糖。把糖放在一片牧场上,他知道N(1<=N<=500)只奶牛会过来舔它,这样就能做出能卖好价钱的超甜黄油。当然,他将付出额外的费用在奶牛上。 农夫John很狡猾。像以前的巴甫洛夫,他知道他可以训练这些奶牛,让它们在听到铃声时去一个特定的牧场。他打算将糖放在那里然后下午发出铃声,以至他可以在晚上挤奶。
农夫John知道每只奶牛都在各自喜欢的牧场(一个牧场不一定只有一头牛)。给出各头牛在的牧场和牧场间的路线,找出使所有牛到达的路程和最短的牧场(他将把糖放在那)。
Input
多组测试数据。第一行: 三个数:奶牛数N,牧场数P(2<=P<=800),牧场间道路数C(1<=C<=1450)。
第二行到第N+1行: 1到N头奶牛所在的牧场号。
第N+2行到第N+C+1行:每行有三个数:相连的牧场A、B,两牧场间距(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
Sample Output
8
[Submit][Status][Web
Board]
题解:
这题迪杰斯特拉算法和弗洛伊德都会超时,这时要用SPFA算法,SPFA有点像bfs,用队列来实现,首先将所有节点dis置为INF,把自身节点dis置为0,把第一个点入队列,然后与他临接的点进行松弛操作,如果可以进行,查看改点是否在队列中,不在则加入队列,当队列为空则完成最短路,遍历一遍节点就可以得出答案
代码:
#include<algorithm> #include<iostream> #include<cstring> #include<stdio.h> #include<math.h> #include<string> #include<stdio.h> #include<queue> #include<stack> #include<map> #include<deque> using namespace std; const int INF=100861111; int p[805][805];//存图 int dis[805];//存单源点的距离 int vis[805];//存点有没有在队列中 int a[805][1455];//存点连接的点坐标 int num[805];//存点通往的点的数目 int cow[505];//存奶牛的标号 int n,m,c; queue<int>q; int minn; int spfa(int x) { int i,j,k; memset(vis,0,sizeof(vis)); for(i=1;i<=m;i++) { dis[i]=INF;//初始化为都不连通状态 } dis[x]=0;//注意 q.push(x); vis[x]=1; int now; while(!q.empty())//进行spfa算法 { now=q.front(); q.pop(); vis[now]=0; for(i=0;i<num[now];i++) { if(dis[now]+p[now][a[now][i]]<dis[a[now][i]])//进行松弛操作 { dis[a[now][i]]=dis[now]+p[now][a[now][i]]; if(!vis[a[now][i]]) { vis[a[now][i]]=1; q.push(a[now][i]); } } } } int sum=0; for(i=0;i<n;i++) { sum+=dis[cow[i]]; } return sum; } int main() { int i,j,k,x,y,v; while(scanf("%d%d%d",&n,&m,&c)!=EOF) { minn=INF; memset(num,0,sizeof(num)); for(i=1;i<=m;i++)//赋值 { for(j=1;j<=m;j++) { p[i][j]=INF; } } for(i=0;i<n;i++) { scanf("%d",&cow[i]); } for(i=0;i<c;i++)//记录图的情况 { scanf("%d%d%d",&x,&y,&v); p[x][y]=v; p[y][x]=v; a[x][num[x]]=y; a[y][num[y]]=x; num[x]++; num[y]++; } for(i=1;i<=m;i++)//枚举所有点 { int t=spfa(i); if(minn>t) minn=t; } printf("%d\n",minn); } return 0; }
ps:
不知道为什么用双向队列可以快很多。。
相关文章推荐
- 【USACO3.2.6】香甜的黄油 最短路径
- 图论-最短路径--3、SPFA算法O(kE)
- 单源最短路径的SPFA算法
- 最短路径 之 SPFA算法
- 最短路径之Spfa算法
- 单元最短路径--SPFA算法
- 最短路径:我的理解--SPFA算法
- 单源最短路径-spfa算法
- SPFA算法 快速Bellaman-ford算法 源点最短路径
- 求含有负权边的图的单源最短路径——Bellman Ford算法与SPFA算法综合分析
- hiho刷题日记——第二十五天最短路径·三:SPFA算法
- 可以处理负权的单源最短路径的SPFA算法带图详解(自己画的图)
- 最短路径SPFA算法
- POJ_2394_最短路径---SPFA算法
- 单源最短路径 ——SPFA算法
- 单点最短路径算法 bellman-ford模板和队列优化后的spfa算法模板
- SPFA算法(求最短路径)
- 最短路径问题 SPFA算法
- HIHO #1093 : 最短路径·三:SPFA算法
- 单源最短路径之SPFA算法实现