题意:ACM队员要到一些点去,并且要从这些点回来,求最短路径总和。
思路:去的时候的最短路径以1为原点用最短路径算法,回来的时候把图每条边给反向以后再以1为原点用最短路径算法。注意的是题目说所有路径的和不超过1000000,但最后的答案不是所有路径的和。不超过1000000只是说保存图的时候可以用int。
图用我用前向星保存,最短路用SPFA
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=1000005;
int dis[maxn];
struct Edge{
int u,v,next;
int w;
}edge1[maxn];
Edge edge2[maxn];
int tot1;
int tot2;
int first1[maxn];
int first2[maxn];
queue<int> que;
void add(int uu,int vv,int ww){
edge1[tot1].u=uu;
edge1[tot1].v=vv;
edge1[tot1].w=ww;
edge1[tot1].next=first1[uu];
first1[uu]=tot1++;
edge2[tot2].u=vv;
edge2[tot2].v=uu;
edge2[tot2].w=ww;
edge2[tot2].next=first2[vv];
first2[vv]=tot2++;
}
void spfa(Edge edge[],int first[]){
memset(dis,-1,sizeof(dis));
dis[1]=0;
while(!que.empty())que.pop();
que.push(1);
while(!que.empty()){
int u=que.front();
que.pop();
for(int i=first[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(dis[v]>dis[u]+edge[i].w||dis[v]==-1){
dis[v]=dis[u]+edge[i].w;
que.push(v);
}
}
}
}
int main(){
// freopen("data.txt","r",stdin);
int n;
scanf("%d",&n);
while(n--){
long long ans=0;
memset(first1,-1,sizeof(first1));
memset(first2,-1,sizeof(first2));
tot1=0;
tot2=0;
int p,q;
scanf("%d%d",&p,&q);
for(int i=0;i<q;++i){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
spfa(edge1,first1);
for(int i=1;i<=p;++i){
ans+=dis[i];
}
spfa(edge2,first2);
for(int i=1;i<=p;++i){
ans+=dis[i];
}
printf("%lld\n",ans);
}
return 0;
}