第一次做SPFA,本来觉得会很难很难写,所以一直都没有去涉及这个方面的题目。在FUZHOU网络赛上遇到了属于SPFA算法的题目,可是我却完全不知道。这次网络预选赛又是3题,还是没能去成现场赛... 最后一年了,我还是这么弱小,A题还是那么慢,所以要好好把握写题的速度尽量快起来!!
SPFA--Bellman-Ford的升级版,却是很好写的。另外几方面还是很省空间的。因为用边来存贮嘛,比如邻接矩阵,在稀疏图的条件下很快很暴力的就可以写出来。
算法我理解的很快,也只写了个裸的SPFA,没有去优化它,多做几个题练练手吧!
代码如下(不懂的可以问我哈):
#include<stdio.h>
#include<queue>
#include<string.h>
#define INF 1234567891011
#define MAXN 1000005
using namespace std;struct Edge
{long v;long price;Edge *next;
}edge[2][MAXN],*ptr[2][MAXN];//存储两个图 另外实现邻接链表!
long dist[MAXN];int V,E;
int edgeNum;void addEdge(long a,long b,long c)
{Edge *p,*q;p=&edge[0][edgeNum];q=&edge[1][edgeNum];edgeNum++;p->v=b;p->price=c;p->next=ptr[0][a];ptr[0][a]=p;q->v=a;q->price=c;q->next=ptr[1][b];ptr[1][b]=q;
}void getEdges()
{int i,j;edgeNum=0;long a,b,c;for( i=1;i<=E;i++ ){scanf( "%lld %lld %lld",&a,&b,&c );addEdge(a,b,c);}
}bool used[MAXN];void SPFA( int graph,int start )
{memset( used,0,sizeof(used) );memset( dist,0x7F,sizeof(dist) );dist[start]=0;queue<int>queue;while( !queue.empty() )queue.pop();queue.push(start);used[start]=true;while( !queue.empty() ){long u=queue.front();queue.pop();Edge *p=ptr[graph][u];while( p!=NULL ){long w=p->price;long v=p->v;p=p->next;if( dist[v]>dist[u]+w ){dist[v]=dist[u]+w;if( !used[v] ){queue.push(v);used[v]=true;}}}used[u]=false;}
}int main()
{int T;scanf( "%d",&T );while( T-- ){scanf( "%d %d",&V,&E );int i,j,k;getEdges();long ans=0;for( k=0;k<2;k++ ){SPFA( k,1 );for( i=2;i<=V;i++ )ans+=dist[i];}printf( "%lld\n",ans );}return 0;
}
这题用的正宗的链表哦~~ 87!