题意:单向图,n个点m条路。问题是求从1到其它点一来一回共多少距离。
按照dijkstra,floyd,bellman都很容易超时。最开始选择的spfa是用vector实现的,也超时了。。。又用数组模拟链表。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define inf 0xFFFFFFFF //大概40多亿
#define maxn 1000010
using namespace std;
class Node
{
public:
int e,v;
int next;
}edge[2][maxn]; //正反储存
int visit[maxn],headlink[2][maxn];
__int64 dis[maxn],ans; //数据很大
int n,m;
void spfa(int pos)
{
for(int i = 1;i <= n; i++)
dis[i] = inf;
memset(visit,0,sizeof(visit));
queue<int>Q;
Q.push(1);
dis[1] = 0;
visit[1] = true;
while(!Q.empty()){
int u = Q.front();
Q.pop();
visit[u] = false;
for(int i = headlink[pos][u];i != -1;i = edge[pos][i].next){ //i是第几条边
int b = edge[pos][i].e;
if(dis[u] + edge[pos][i].v > dis[b])
continue;
dis[b] = dis[u] + edge[pos][i].v;
if(!visit[b]){
Q.push(b);
visit[b] = true;
}
}
}
}
int main()
{
// freopen("in.txt","r",stdin);
int ncase;
scanf("%d",&ncase);
while(ncase--){
scanf("%d%d",&n,&m);
for(int i = 1;i <= n; i++){ //判断链表是否到表尾
headlink[0][i] = -1;
headlink[1][i] = -1;
}
int a,b,c;
for(int i = 1;i <= m; i++){
scanf("%d%d%d",&a,&b,&c);
edge[0][i].v = c;
edge[0][i].e = b;
edge[0][i].next = headlink[0][a];
headlink[0][a] = i; //表头
edge[1][i].v = c;
edge[1][i].e = a;
edge[1][i].next = headlink[1][b];
headlink[1][b] = i;
}
spfa(0);
ans = 0;
for(int i = 1;i <= n; i++)
ans += dis[i];
spfa(1);
for(int i = 1;i <= n; i++)
ans += dis[i];
printf("%I64d\n",ans);
}
return 0;
}