HDU 1535 Invitation Cards(Dijkstra)
http://acm.hdu.edu.cn/showproblem.php?pid=1535
题意:
题意很简单,给你n个点的有向图,要求n-1个人从1号点走到剩下n-1个点去,计算总距离s1.然后这n-1个人从这n-1个点回到1号点,计算总距离s2.问s1+s2的最小值.(且该图强连通)
分析:
明显去的时候和回来的时候每个人都要走最短路径了.可以用Floyd算法算.但是用两次Dijkstra算法更快.
首先原始有向图我们用Dijkstra求出从1号点到其他所有点的最短距离然后相加即可得s1.
对于其他所有点到1号点的最短距离如何求? 我们只需要将原始边反向.建立一个反向边的有向图,然后用Dijkstra求出1号点到其他所有点的最短距离和即为所求s2.(想想为什么)
AC代码:
#include<cstdio> #include<cstring> #include<vector> #include<queue> #include<algorithm> using namespace std; const int maxn = 100000+10; //这里如果取100W,会超内存 #define INF 1e9 struct Edge { int from,to,dist; Edge(int f,int t,int d):from(f),to(t),dist(d){} }; struct HeapNode { int d,u; HeapNode(int d,int u):d(d),u(u){} bool operator <(const HeapNode &rhs)const { return d>rhs.d; } }; struct Dijkstra { int n,m; vector<Edge> edges; vector<int> G[maxn]; bool done[maxn]; int d[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) { edges.push_back(Edge(from,to,dist)); m = edges.size(); G[from].push_back(m-1); } void dijkstra() { priority_queue<HeapNode> Q; for(int i=0;i<n;i++) d[i]=INF; d[0]=0; memset(done,0,sizeof(done)); Q.push(HeapNode(d[0],0)); 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; Q.push(HeapNode(d[e.to],e.to)); } } } } }DJ_1,DJ_2; int main() { int T; scanf("%d",&T); while(T--) { int n,m; scanf("%d%d",&n,&m); DJ_1.init(n),DJ_2.init(n); for(int i=0;i<m;i++) { int u,v,d; scanf("%d%d%d",&u,&v,&d); u--,v--; DJ_1.AddEdge(u,v,d); DJ_2.AddEdge(v,u,d); } DJ_1.dijkstra(); DJ_2.dijkstra(); int ans=0; for(int i=1;i<n;i++) { ans += DJ_1.d[i]; ans += DJ_2.d[i]; } printf("%d\n",ans); } return 0; }