【Step1】【SPFA最短路】poj 1847-Tram
题目大意:
输入数据中,第一行给出n个点,起点和终点。
接下来n行,每行第一个数x,xi为第i个点和几个点有边。接下来x个数,到第一个点代价为0,其余为1。
求从起点到终点的最小代价。
这里是我们讲的第一个算法:SPFA(shortest-path-fastest-algorithm,最短路快速算法)
最短路顾名思义,就是求最短的道路,在我们的生活中也很常用。SPFA主要是解决从一个固定的点到其他点的最短路。(又叫做:单源最短路)
具体的可以去看别人的博客,我们简单的讲一讲吧。
SPFA类似DP(动态规划)的思想。用数组f[i]表示从st点到达各个点的最小代价。
我们从起点向各个和它相连的点更新。如果新更新的点y能够取到比原来更小的值。那么相应的,从y到其他点的值会更小。
我们用一个队列存储接下来要更新的点。直到怎么都无法找到更优解,我们就停止。
具体代码如下:
while(head!=tail) { int x=q[head];//队列 for(int i=first[x];i!=0;i=a[i].next) { int y=a[i].y; if(f[y]>f[x]+a[i].d) { f[y]=f[x]+a[i].d; if(tf[y]==false) { tf[y]=true;//当然,如果这个点本来就在之后要更新的点之中,我们就不需要再次加入队列。 q[tail]=y; tail++; if(tail>n)tail=1;//循环队列,不展开来讲了 } } } tf[x]=false;//它还有可能加入队列,所以记得还原 head++; if(head>n)head=1; }
那么这一道题的代码也就呼之欲出了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 struct qq{ 5 int x,y,d,next; 6 }a[20005]; 7 int first[105]; 8 int f[105]; 9 bool tf[105]; 10 int q[105]; 11 int n,st,ed,len=0; 12 void make_l(int x,int y,int d) 13 { 14 len++; 15 a[len].x=x; 16 a[len].y=y; 17 a[len].d=d; 18 a[len].next=first[x]; 19 first[x]=len; 20 //printf("%d %d %d\n",a[len].x,a[len].y,a[len].d); 21 } 22 int main() 23 { 24 scanf("%d %d %d",&n,&st,&ed); 25 len=0; 26 memset(first,0,sizeof(first)); 27 memset(f,63,sizeof(f)); 28 for(int i=1;i<=n;i++) 29 { 30 int xx; 31 scanf("%d",&xx); 32 for(int j=1;j<=xx;j++) 33 { 34 int y; 35 if(j==1) 36 { 37 scanf("%d",&y); 38 make_l(i,y,0); 39 } 40 else { 41 scanf("%d",&y); 42 make_l(i,y,1); 43 } 44 } 45 } 46 int head=1,tail=2; 47 memset(tf,false,sizeof(tf));tf[st]=true; 48 f[st]=0;q[1]=st; 49 //printf("%d",f[1]); 50 while(head!=tail) 51 { 52 int x=q[head]; 53 for(int i=first[x];i!=0;i=a[i].next) 54 { 55 int y=a[i].y; 56 if(f[y]>f[x]+a[i].d) 57 { 58 f[y]=f[x]+a[i].d; 59 if(tf[y]==false) 60 { 61 tf[y]=true; 62 q[tail]=y; 63 tail++; 64 if(tail>n)tail=1; 65 } 66 } 67 } 68 tf[x]=false; 69 head++; 70 if(head>n)head=1; 71 } 72 if(f[ed]>=1061109567)printf("-1\n"); 73 else 74 printf("%d",f[ed]); 75 return 0; 76 }