题目大意:让你求出从原点到其他各个点来回的最短路径之和。
算法思想:首先正向建图,求出原点到各个点之间最短路径之和,在反向建图,再求一遍原点到各个点之间最短路之和(可以看做是各个点到远点的最短路,因为这时候原点到各个点的距离==各个点到原点的距离,这道题昨天不知道什么原因,wa了不下10次,今天上午一样的算法,一样的写法,重新写一遍 。。1A也是醉了).。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; #define INF 1e10 #define MAXN 1000050 int t; int a,b,n,m,e; long long cc,res; typedef struct Edge { int u; int v; long long c; }; int head[MAXN],next[MAXN*2],dist[MAXN]; Edge edges[MAXN*2]; bool visited[MAXN]; void addNode(int u,int v,long long c) { edges[e].u=u; edges[e].v=v; edges[e].c=c; next[e]=head[u]; head[u]=e++; } bool relax(int u,int v,long long c) { if(dist[v]>dist[u]+c) { dist[v]=dist[u]+c; return true; } return false; } long long spfa(int src) { long long ans=0; memset(visited,false,sizeof(visited)); for(int i=1;i<=n;i++) { dist[i]=INF; } dist[src]=0; queue<int>que; que.push(src); visited[src]=true; while(!que.empty()) { int q=que.front(); que.pop(); visited[q]=false; for(int i=head[q];i+1;i=next[i]) { if(relax(q,edges[i].v,edges[i].c)&&!visited[edges[i].v]) { visited[edges[i].v]=true; que.push(edges[i].v); } } } for(int i=1;i<=n;i++) { ans+=dist[i]; } return ans; } int main() { scanf("%d",&t); while(t--) { memset(head,-1,sizeof(head)); memset(next,-1,sizeof(next)); e=1; res=0; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d%lld",&a,&b,&cc); addNode(a,b,cc); } res+=spfa(1); memset(head,-1,sizeof(head)); memset(next,-1,sizeof(next)); e=1; for(int i=1;i<=m;i++) { addNode(edges[i].v,edges[i].u,edges[i].c); } res+=spfa(1); printf("%lld\n",res); } return 0; }