题意,求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;
}