洛谷 P1828 香甜的黄油 Sweet Butter
题意
有N头牛,P个牧场,C个道路,给出牛在的牧场和牧场之间的道路,求出所有牛到同一个牧场(最优解)的最短路。
做法
因为这道题牧场很多,但边的数量较少,所以我们可以用SPFA做这道题,用一个循环队列,用链表存牧场之间的道路,然后模拟从所有牧场出发的所有情况,求最短路即可。
代码
#include<bits/stdc++.h> using namespace std; int head[805],to[3005],net[3005],juli[3005]; int n,p,c,pp; int x,y,s; int cow[505]; void lianbiao(int a,int b,int c) { to[++pp]=b;//下一条边连接的点更新成 b(y) juli[pp]=c;//距离更新成c(s) net[pp]=head[a];//下一个点的下一个点更新成原先的head(也就是原先的下一个点) head[a]=pp;//下一条边更新成 pp这条边 }//头插法,时间复杂度较低 int SPFA(int k) { int q[805];//队列 int v[805]={};//记录点是否出现在队列里 int d[805];//距离 for(int i=1;i<=p;++i) d[i]=1e9;//初始化 d[k]=0;//一开始的距离是 0 v[k]=1;//进入队列 int tou=0; int wei=1; q[wei]=k; while(tou!=wei)//循环队列 { tou=(tou+1)%p; int l=q[tou]; for(int i=head[l];i!=0;i=net[i]) { int j=to[i]; int D=juli[i]; if(d[j]>d[l]+D) { d[j]=d[l]+D;//更新 if(!v[j]) { wei=(wei+1)%p; q[wei]=j; v[j]=1; } } } v[l]=0;//移除队列 } int sum=0; for(int i=1;i<=n;++i) sum+=d[cow[i]]; return sum; } int main() { freopen("butter.in","r",stdin); freopen("butter.out","w",stdout); scanf("%d%d%d",&n,&p,&c); for(int i=1;i<=n;++i) scanf("%d",&cow[i]); for(int i=1;i<=c;++i) { scanf("%d%d%d",&x,&y,&s); lianbiao(x,y,s); lianbiao(y,x,s);//路是双向的 } int ans=1e9;//记录答案 for(int i=1;i<=p;++i) ans=min(ans,SPFA(i));//求最短路 printf("%d\n",ans); return 0; }