题意,求0点到N-1点的来回最短路。
这题是基础spfa题:
坑爹的用了一个下午的时间弄,这题的输入居然要用scanf,为啥没hit提示呢,以后遇到TLE就要考虑是否输入的问题了。
总结下spfa算法,比较高效的算法,有点繁琐,主要是利用了邻接表和队列的形式,与bfs很像。
同时可以利用入队次数到达V判断是否有负环。
spfa优化算法在这题用不着。。
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int maxn=0x3f3f3f3f; const int N=1000005; const int E=1000005; struct Edge{ int pnt; int dis; int next; }edge1[E],edge2[E]; int n,e,cur,aver; int neigh1[N],neigh2[N]; int que[N],mindis[N],front,rear; bool vis[N]; void spfa(int s,int v) { Edge *edge; int *neigh; if(v==1) { edge=edge1; neigh=neigh1; } else { edge=edge2; neigh=neigh2; } for(int i=0;i<n;i++) { mindis[i]=maxn; vis[i]=false; } int averge=aver/cur; int num=cur; front=rear=0; //s入队 mindis[s]=0; que[rear++]=s; while(front!=rear) { int pre=que[front]; vis[pre]=false; int t=neigh[pre]; while(t!=-1) { int pnt= edge[t].pnt; if(mindis[pnt]>mindis[pre]+edge[t].dis) { mindis[pnt]=mindis[pre]+edge[t].dis; if(!vis[pnt]) { vis[pnt]=true; que[rear++]=pnt; if(mindis[que[rear-1]]<mindis[que[front]])//SLF优化算法 swap(que[rear-1],que[front]); if(rear==N) rear=0; } } t=edge[t].next; } if(++front==N) {front=0;} } } int main() { int T,begin,end,dis; long long sum; scanf("%d", &T); while(T--) { cur=0; aver=0; scanf("%d%d", &n, &e); for(int i =0;i<n;i++)neigh1[i]=neigh2[i]=-1; for(int i =0;i<e;i++) { scanf("%d%d%d", &begin, &end, &dis); begin--; end--; aver+=dis; edge1[cur].pnt=end; edge1[cur].dis=dis; edge1[cur].next=neigh1[begin]; neigh1[begin]=cur; edge2[cur].pnt=begin; edge2[cur].dis=dis; edge2[cur].next=neigh2[end]; neigh2[end]=cur; cur++; } sum=0; spfa(0,1); for(int i=1;i<n;i++)sum+=mindis[i]; spfa(0,2); for(int i=1;i<n;i++)sum+=mindis[i]; printf("%lld\n", sum); } return 0; }