SPFA+寻路(行路难,洛谷2832)
SPFA加寻路的操作只需要多添加一个数组记录路径即可。
我们把这个数组叫做G数组,G数组里的数要求满足SPFA的判断条件时才会执行。也就是SPFA路径。
1 void find(int x) 2 { 3 if(G[x]==0){ 4 printf("%d ",1); 5 return; 6 } 7 find( G[x] ); 8 printf("%d ",x); 9 }
通过这个函数查询每个点的钱一个路径,因为1号点没有前一个路径,所以好手动输出。
具体操作以洛谷2832为例:http://www.luogu.org/problem/show?pid=2832
第17行为G数组的定义,61行为G数组的应用,在SPFA条件满足的时候,我们就把G数组的值进行了更改。最后通过71行的函数进行查询即可。
关于这道题还有一个难点就是疲劳值:因为疲劳值是每走一条路径再走任意一条路径都会增加1,但是如果每次都对所有的边进行修改,那时间复杂度和难度都很现实,所有我们采取曲线救国的思想,对当前的点添加一个疲劳值,从这个点向外走的话,我们就要加上这个疲劳值 ( dis[当前点] + edge[i].val +fit[当前点] < dis[ 指向点 ] )dis就是从原点开始到当前点的距离,edge[i].val就是权值,再加上当前点fit(疲劳值)如果还是小于下一个点的距离的话,我们就替换,相比以前的SPFA多加了一个fit。
fit的计算方法为:fit[指向点]=fit[当前点]+1;只要满足SPFA的条件就执行,不要在意会不会覆盖掉之前的,因为这是最近的点的fit,就算之前的比这个小,但是你的总体值是比之前的总体值小的,如果当前值不会的话,会在后期的SPFA判断里从新修改,所以不用担心覆盖之前的值。
具体剩下的看代码就好。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 #define MAX 10005 7 #define MAXM 200005 8 //============================================================================== 9 struct NODE{ 10 int point,val,next_edge; 11 int last_spot; 12 NODE(){ next_edge=0; 13 last_spot=0; 14 } 15 }edge[MAXM]; 16 //============================================================================== 17 int N,M,G[MAX],fit[MAX];//疲劳值和路径 18 queue<int> que; 19 int edgenum=0,link[MAX],vister[MAX],dis[MAX]; 20 //============================================================================== 21 void intit(); 22 void ADD(int ,int ,int); 23 void SPFA(); 24 void find(int); 25 //============================================================================== 26 void init() 27 { 28 memset( dis , 0x3f3f3f3f , sizeof(dis) ); 29 int aa,bb,cc; 30 cin>>N>>M; 31 for(int i=1;i<=M;i++){ 32 scanf("%d%d%d*c",&aa,&bb,&cc); 33 ADD( aa , bb , cc ); 34 } 35 } 36 //============================================================================== 37 void ADD(int last, int next,int val) 38 { 39 edgenum++; 40 edge[edgenum].point=next; 41 edge[edgenum].val=val; 42 edge[edgenum].next_edge=link[last]; 43 link[last]=edgenum; 44 } 45 //============================================================================== 46 void SPFA() 47 { 48 que.push(1); 49 vister[1]=1; 50 dis[1]=0; 51 //============================ 52 while(!que.empty()){ 53 int temp=que.front(); 54 que.pop(); 55 vister[temp]=0; 56 //========================= 57 for(int i=link[temp]; i!=0 ; i=edge[i].next_edge ){ 58 if( dis[temp] + edge[i].val +fit[temp] < dis[ edge[i].point ] ){ 59 dis[ edge[i].point ]=dis[temp]+edge[i].val+fit[temp]; 60 fit[edge[i].point]=fit[temp]+1; 61 G[ edge[i].point ]=temp; 62 if( vister[ edge[i].point ] == 0 ){ 63 vister[edge[i].point]=1; 64 que.push(edge[i].point); 65 } 66 } 67 } 68 } 69 } 70 //============================================================================== 71 void find(int x) 72 { 73 if(G[x]==0){ 74 printf("%d ",1); 75 return; 76 } 77 find( G[x] ); 78 printf("%d ",x); 79 } 80 //============================================================================== 81 int main() 82 { 83 init(); 84 SPFA(); 85 printf("%d\n",dis[N]); 86 find(N); 87 //system("pause"); 88 return 0 ; 89 }