POJ 3268 Silver Cow Party
博客搬新家,以后就是基本只在自己的独立博客进行更新,欢迎访问。http://zihengoi.cn
题目描述:
题目描述:POJ 3268 Silver Cow Party
题目大意:
有
N
个农场,在这些农场里有
解题思路:
题目说至少花多少时间在来回的路上,也就是说在求再来回路上用时最短的母牛的所用时间。显然可以将这个划分为两部分。
- 每只牛从
X 农场回到自己农场的时间:这个很简单,直接对于X农场用 dijkstra 求到各点的最短距离即可。- 每只牛前往
X
农场所用时间:用到了一个技巧叫做,转置矩阵。之前我们求了每只牛回到自己农场的时间。现在只要把给的矩阵按照
fm2[j][i]=fm1[i][j] 转置,重新对X农场用 Dijkstra 求一次即可。
- 每只牛前往
X
农场所用时间:用到了一个技巧叫做,转置矩阵。之前我们求了每只牛回到自己农场的时间。现在只要把给的矩阵按照
-
- 最终要找的最短时间:找出的
d1[i]+d2[i]
的最小值即可。
复杂度分析:
时间复杂度 : O(n2)
空间复杂度 : O(n2)AC代码:
#include <cstdio> #include <cstring> #include <cmath> #include <queue> #include <iostream> using namespace std; const int maxn = 1010; const int INF = 0x3fffffff; int fm1[maxn][maxn],fm2[maxn][maxn]; struct Heapnode{ int d,u; bool operator < (const Heapnode& rhs) const{ return d > rhs.d; } }; struct Edge{ int form,to,dist; }; struct Diskstra{ int n,m; vector<Edge> edges; vector<int> G[maxn]; bool done[maxn]; int d[maxn]; 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){ edges.push_back((Edge){from,to,dist}); m = edges.size(); G[from].push_back(m-1); } void dijkstra(int 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}); } } } } }; void trans(int n){ for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) fm2[j][i] = fm1[i][j]; } int main(){ int x,n,m; while(scanf("%d%d%d",&n,&m,&x) != EOF){ Diskstra ans1,ans2; ans1.n = ans2.n = n; ans1.m = ans2.m = m; ans1.init(n); ans2.init(n); memset(fm1,-1,sizeof(fm1)); memset(fm2,-1,sizeof(fm2)); for(int i = 0; i < m ;i++){ int from,to,dist; scanf("%d%d%d",&from,&to,&dist); fm1[--from][--to] = dist; } trans(n); for(int i = 0; i < n; i++) for(int j = 0; j < n; j++){ if(fm1[i][j] > 0) ans1.AddEdge(i,j,fm1[i][j]); if(fm2[i][j] > 0) ans2.AddEdge(i,j,fm2[i][j]); } x--; ans1.dijkstra(x); ans2.dijkstra(x); int ans = 0; for(int i = 0; i < n; i++){ if(ans1.d[i] + ans2.d[i] > ans) ans = ans1.d[i] + ans2.d[i]; } printf("%d\n",ans); } return 0; }
- 最终要找的最短时间:找出的
d1[i]+d2[i]
的最小值即可。