战争和物流(uvalive 4080)
2018-02-06 14:35
459 查看
题目链接 https://vjudge.net/problem/UVALive-4080
题意
给定一个n节点m条边的无向图,定义c为每对顶点的最短路之和,要求删掉一条边重新求一个c值c’,求出c’最大值.
思路
大白书330页例题,如果用floyd算法计算c,每尝试删除一条边都要重新计算一次,时间复杂度为O(n*n*n*m),很难承受。如果用n次Dijkstra计算单源最短路,时间复杂度味O(n*m*m*logn)。虽然看上去比之前的好,但由于佛洛依德算法的常数很小,实际运行时间差不多。这时候,可以考虑最短路树。因为在源点确定的情况下,只要最短路树不被破坏,起点到所有点的距离都不会发生改变。也就是说,只有删除最短路树上的n-1条边,最短路树才需要重新计算。这样,对于每个源点,最多只需求n次最短路而不是m次,时间复杂度降为O(n*n*m*logn),可以承受。而且在有重边时删除一条边应当用第二短的边来代替。
题意
给定一个n节点m条边的无向图,定义c为每对顶点的最短路之和,要求删掉一条边重新求一个c值c’,求出c’最大值.
思路
大白书330页例题,如果用floyd算法计算c,每尝试删除一条边都要重新计算一次,时间复杂度为O(n*n*n*m),很难承受。如果用n次Dijkstra计算单源最短路,时间复杂度味O(n*m*m*logn)。虽然看上去比之前的好,但由于佛洛依德算法的常数很小,实际运行时间差不多。这时候,可以考虑最短路树。因为在源点确定的情况下,只要最短路树不被破坏,起点到所有点的距离都不会发生改变。也就是说,只有删除最短路树上的n-1条边,最短路树才需要重新计算。这样,对于每个源点,最多只需求n次最短路而不是m次,时间复杂度降为O(n*n*m*logn),可以承受。而且在有重边时删除一条边应当用第二短的边来代替。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int inf = 0x3f3f3f3f; const int maxn = 105; const int maxm = 1050; int n, m, L; int p[maxn]; ll ans[maxm << 1]; 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 dd, int uu) :d(dd), u(uu) {} 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]; int p[maxn]; int del = -1;//被删除的边的编号(通过del^1找相对称的边) void init(int n) { this->n = n; for (int i = 0; i < n; ++i) g[i].clear(); edges.clear(); } void add(int from, int to, int dist) { edges.push_back(Edge(from, to, dist)); m = edges.size(); g[from].push_back(m - 1); } ll dijkstra(int s) { priority_queue<HeapNode> que; for (int i = 0; i < n; ++i) d[i] = inf; d[s] = 0; memset(done, 0, sizeof(done)); que.push(HeapNode(0, s)); while (!que.empty()) { HeapNode x = que.top(); que.pop(); int u = x.u; if (done[u]) continue; done[u] = true; for (int i = 0; i < g[u].size(); ++i) { if (del != g[u][i] && (del ^ 1) != g[u][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]; que.push(HeapNode(d[e.to], e.to)); } } } } ll ans = 0; for (int i = 0; i < n; ++i) { if (i == s) continue; ans += d[i] == inf ? L : d[i]; } return ans; } }solver; int main() { while (scanf("%d%d%d", &n, &m, &L) == 3) { solver.init(n); memset(ans, 0, sizeof(ans)); for (int i = 0; i < m; ++i) { int u, v, c; scanf("%d%d%d", &u, &v, &c); --u, --v; solver.add(u, v, c); solver.add(v, u, c); } ll ans1 = 0, ans2 = 0; for (int s = 0; s < n; ++s) {//枚举所有点作为源点 ll tmp = solver.dijkstra(s); memcpy(p, solver.p, sizeof(p)); ans1 += tmp; for (int i = 0; i < 2 * m; ++i) ans[i] += tmp; for (int i = 0; i < n; ++i) {//把最短路树上的边依次删除,再求最短路 if (i == s) continue; solver.del = p[i]; ans[p[i]] = ans[p[i] ^ 1] = ans[p[i]] - tmp + solver.dijkstra(s); //无向图每条边添加了2次,p[i]^1其实就是找和p[i]边相同的另一条边 } solver.del = -1;//每次算完记得重新把del置为-1(-1^1==-2,而边的下标是0到2*m-1,所以对求最短路无影响) } for (int i = 0; i < 2 * m; ++i) { ans2 = max(ans2, ans[i]); } printf("%lld %lld\n", ans1, ans2); } return 0; }
相关文章推荐
- UVA 4080 Warfare And Logistics 战争与物流 (最短路树,变形)
- UVALive4080[Warfare And Logistics] 最短路树+dijkstra
- LA 4080 战争和物流(最短路树)
- LA 4080 Warfare And Logistics 战争和物流 dijkstra 最短路树
- uvalive 4080 Warfare And Logistics(最短路树)
- UVALive 4080 Warfare And Logistics (最短路树)
- HDU 4080 UVaLive 4513 - Stammering Aliens (字符串hash)
- UVALive - 4080 Warfare And Logistics
- UVAlive4080_Warfare And Logistics
- UVALive 4080 Warfare And Logistics(最短路树)
- UVALive - 4080 Warfare And Logistics (SPFA+最短路树)
- UVALive 4080 Warfare And Logistics
- UVALive 4080 最短路树
- Dijkstra,最短路树(战争和物流,LA 4080)
- UVALive 4080 Warfare And Logistics(Dijkstra+最短路树)
- UVALive 4035 Undetectable Tour (二分 + 并查集)
- UVaLive 3490 - Generator (AC自动机 期望DP 高斯消元)
- POJ2864 UVALive3470 Pascal Library【水题】
- UVALive 6886 Golf Bot(FFT)
- (trie)UVALive - 3942 Remember the Word