给出图的有向边,求源点到其它所有点的最短距离之和sum1和其他点到源点的最短路径和sum2,sum1+sum2即为所求 按图中输入构造一个邻接表,然后将所有边转置后构造一个邻接表,用这两个表求两次最短路径,将他们的和相加即为结果 #include <iostream> #include <queue> using namespace std; /* 传入源点s,numv存储点的个数,用dis数组存下最短路径值 edge[]为其邻接表 */ class node { public: int v,w; node *next; }; const int inf=0x7fffffff; const int MAXN=1000005; bool visit[MAXN]; int numv,pos; int dis_1[MAXN],dis_2[MAXN]; node edge1[MAXN],edge2[MAXN],g[MAXN*2]; void add_edge(int &u,int &v,int &w) //建立邻接表 { node *ptr = &g[pos++]; ptr->v=v; ptr->w=w; ptr->next=edge1[u].next; edge1[u].next=ptr; node *ptr2 = &g[pos++]; //将所有边转置后的新表 ptr2->v=u; ptr2->w=w; ptr2->next=edge2[v].next; edge2[v].next=ptr2; } void spfa(int s,int dis[],node edge[]) { node *ptr; int tmp,t,sz; queue<int> que; dis[s] = 0; que.push(s); while(!que.empty()) { tmp = que.front(); que.pop(); visit[tmp] = false; for(ptr = edge[tmp].next;ptr!=NULL;ptr=ptr->next) { t = ptr->w; if(dis[ptr->v] > dis[tmp]+t) { dis[ptr->v] = dis[tmp] + t; if(!visit[ptr->v]) //若该点不在队列中,则入队,并修改相应的信息 { visit[ptr->v] = true; que.push(ptr->v); } } } } } int main() { int i,cas,q,u,v,w,j; __int64 sum1,sum2; node tmp; scanf("%d",&cas); while (cas--) { scanf("%d%d",&numv,&q); sum1=0; sum2=0; pos=0; for(i=1;i<=numv;++i) { visit[i] = false; dis_1[i] = inf; dis_2[i] = inf; edge1[i].next=NULL; edge2[i].next=NULL; } //init for(i=0;i<q;++i) { scanf("%d%d%d",&u,&v,&w); add_edge(u,v,w); } //构图 spfa(1,dis_1,edge1); for(i=1;i<=numv;++i) sum1+=dis_1[i]; spfa(1,dis_2,edge2); for(i=1;i<=numv;++i) sum2+=dis_2[i]; printf("%I64d/n",sum1+sum2); } return 0; }