题意:
在有向加权图中G(V,E),邮局要从起点S向其他n个节点发送邮件,于是派出n个邮递员,分别到达其他n个地点发送,然后回到起点S,求出所有邮递员所经过的总路程的最小值。
分析:
正向一次dijkstra,反向一次dijkstra
// File Name: 2008.cpp // Author: Zlbing // Created Time: 2013年08月04日 星期日 14时18分49秒 #include<iostream> #include<string> #include<algorithm> #include<cstdlib> #include<cstdio> #include<set> #include<map> #include<vector> #include<cstring> #include<stack> #include<cmath> #include<queue> using namespace std; #define CL(x,v); memset(x,v,sizeof(x)); #define INF 0x3f3f3f3f #define LL long long #define REP(i,r,n) for(int i=r;i<=n;i++) #define RREP(i,n,r) for(int i=n;i>=r;i--) const int MAXN=1e6+100; struct Edge{ int from,to,dist; }; struct HeapNode{ int d,u; bool operator <(const HeapNode &rhs)const{ return d>rhs.d; } }; vector<int> O_G[MAXN]; vector<Edge> O_edges; struct Dijkstra{ int n,m;//点和边数 vector<Edge>edges;//边列表 vector<int>G[MAXN];//每个节点出发的边编号(从0开始编号) bool done[MAXN];//是否永久标记 int d[MAXN];//s到各个点的距离 int p[MAXN];//最短路中的上一条边 void init(int n) { this->n=n; for(int i=0;i<=n;i++)//清空邻接表 { G[i].clear(); } edges.clear();//清空边表 } void AddEdge(int from,int to,int dist) { //如果是无向图,每条无向边需调用2次AddEdge edges.push_back((Edge){from,to,dist}); m=edges.size(); G[from].push_back(m-1); } void dijkstra(int s) {//求s到所有点的距离 priority_queue<HeapNode> Q; for(int i=0;i<=n;i++)d[i]=INF; d[s]=0; memset(done,0,sizeof(done)); Q.push((HeapNode){0,s}); while(!Q.empty()) { HeapNode x=Q.top();Q.pop(); int u=x.u; if(done[u])continue; done[u]=true; for(int i=0;i<G[u].size();i++) { Edge& e=edges[G[u][i]]; if(d[e.to]>d[u]+e.dist) { d[e.to]=d[u]+e.dist; p[e.to]=G[u][i]; Q.push((HeapNode){d[e.to],e.to}); } } } } }; Dijkstra solver; int main() { int N; scanf("%d",&N); while(N--) { int n,m; scanf("%d%d",&n,&m); solver.init(n); int a,b,c; for(int i=0;i<=n;i++) O_G[i].clear(); O_edges.clear(); for(int i=0;i<m;i++) { scanf("%d%d%d",&a,&b,&c); solver.AddEdge(a,b,c); O_edges.push_back((Edge){b,a,c}); int mm=O_edges.size()-1; O_G[b].push_back(mm); } solver.dijkstra(1); int ans=0; for(int i=1;i<=n;i++) ans+=solver.d[i]; for(int i=1;i<=n;i++) solver.G[i]=O_G[i]; solver.edges=O_edges; solver.dijkstra(1); for(int i=1;i<=n;i++) ans+=solver.d[i]; printf("%d ",ans); } return 0; }