这题目限制是8000ms,一看就不怎么做得下去了,但题目意思倒是很简单
求源点到其他各个点之和 加上 其他各个点到源点之和的最小值
建立正反两个邻接表,作正反两次最短路,SPFA
逆序的情况:在初始化的时候在反向保存另一相同表
即: 1 ---> 2 13
反向后:2 ---> 1 13
要求各点到源点的距离和,即求源点到各点的距离和
所以,处理好后,只要求两次源点到各点距离和相加即可
#include <iostream> #include<string> #include<stdlib.h> using namespace std; const int MAX = 1000001; const int inf = INT_MAX; int N,m,n,num; typedef struct vol { int w,//当前位置 v,//价值 value next;//下一结点的位置 } Voll; Voll peo[MAX*2]; bool vis[MAX]; int start1[MAX], start2[MAX]; int stack[MAX]; int dis[MAX]; // dis[i] 从1即到i当前最短路 __int64 SPFA( int startt[]) { int i,top=0,temp; temp = 1; for(i=0;i<n+1;i++) { dis[i] = inf; } memset(vis,false,sizeof(vis)); dis[temp] = 0; stack[++top] = temp; vis[temp]=true; while(top) { temp =stack[top--];vis[temp]=false; for(i=startt[temp]; i!=-1; i=peo[i].next) { if(peo[i].v + dis[temp] < dis[peo[i].w]) { dis[peo[i].w] = peo[i].v + dis[temp]; if(!vis[peo[i].w]) { vis[peo[i].w]=true; stack[++top] = peo[i].w; } } } } __int64 sum=0; for(i=1;i<=n;i++) { sum+=dis[i]; } return sum; } void init() { scanf("%d %d", &n, &m); int i,x,y,v; num=0; memset(start1,-1,sizeof(start1)); memset(start2,-1,sizeof(start2)); for(i=0;i<m;i++) { scanf("%d %d %d",&x,&y,&v); peo[num].w = y; peo[num].v = v; peo[num].next = start1[x]; //保存邻接表串的始端位置,逆向实现相当给力!!! start1[x] = num++; ///反向 peo[num].w = x; peo[num].v = v; peo[num].next = start2[y]; start2[y] = num++; } } int main() { scanf("%d", &N); while(N--) { init(); printf("%I64d\n", SPFA(start1) + SPFA(start2)); } return 0; }