战争和物流,白书P330LA4080(dijkstra,单源最短路树优化)
2017-11-18 22:50
357 查看
本题目综合性非常强,要反复体会。
知识积累:
1.优化版的dijkstra算法的时间复杂度为mlogn
floyd算法的时间复杂度为n方。
2.这两个算法都是研究简单图的,两个点之间没有重复边。
3.而本题的最大陷阱就是,两点之间可能有重复边。当有重复边的情况时,如果最短变被拿掉的,应该用第二短边来替代。所以题目中用了一个数组来保存两点之间的所有权。
4.本题的算法综合性非常强,需要反复体会。
知识积累:
1.优化版的dijkstra算法的时间复杂度为mlogn
floyd算法的时间复杂度为n方。
2.这两个算法都是研究简单图的,两个点之间没有重复边。
3.而本题的最大陷阱就是,两点之间可能有重复边。当有重复边的情况时,如果最短变被拿掉的,应该用第二短边来替代。所以题目中用了一个数组来保存两点之间的所有权。
4.本题的算法综合性非常强,需要反复体会。
// LA4080/UVa1416 Warfare And Logistics // Rujia Liu #include<cstdio> #include<cstring> #include<vector> #include<algorithm> #include<queue> using namespace std; const int INF = 1000000000; const int maxn = 100 + 10; struct Edge { int from, to, dist; }; struct HeapNode { int d, 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]; // 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) { 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(e.dist > 0 && d[e.to] > d[u] + e.dist) { // 此处和模板不同,忽略了dist=-1的边。此为删除标记。根据题意和dijkstra算法的前提,正常的边dist>0 d[e.to] = d[u] + e.dist; p[e.to] = G[u][i]; Q.push((HeapNode){d[e.to], e.to}); } } } } }; //////// 题目相关 Dijkstra solver; int n, m, L; vector<int> gr[maxn][maxn]; // 两点之间的原始边权 int used[maxn][maxn][maxn]; // used[src][a][b]表示源点为src的最短路树是否包含边a->b int idx[maxn][maxn]; // idx[u][v]为边u->v在Dijkstra求解器中的编号 int sum_single[maxn]; // sum_single[src]表示源点为src的最短路树的所有d之和 int compute_c() { int ans = 0; memset(used, 0, sizeof(used)); for(int src = 0; src < n; src++) { solver.dijkstra(src); sum_single[src] = 0; for(int i = 0; i < n; i++) { if(i != src) { int fa = solver.edges[solver.p[i]].from;//构造单源最短路数树 used[src][fa][i] = used[src][i][fa] = 1; } sum_single[src] += (solver.d[i] == INF ? L : solver.d[i]); } ans += sum_single[src]; } return ans; } int compute_newc(int a, int b) { int ans = 0; for(int src = 0; src < n; src++) if(!used[src][a][b]) ans += sum_single[src]; else { solver.dijkstra(src); for(int i = 0; i < n; i++) ans += (solver.d[i] == INF ? L : solver.d[i]); } return ans; } int main() { while(scanf("%d%d%d", &n, &m, &L) == 3) { solver.init(n); for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) gr[i][j].clear(); for(int i = 0; i < m; i++) { int a, b, s; scanf("%d%d%d", &a, &b, &s); a--; b--; gr[a][b].push_back(s); gr[b][a].push_back(s); } // 构造网络 for(int i = 0; i < n; i++) for(int j = i+1; j < n; j++) if(!gr[i][j].empty()) { sort(gr[i][j].begin(), gr[i][j].end()); solver.AddEdge(i, j, gr[i][j][0]); idx[i][j] = solver.m - 1; solver.AddEdge(j, i, gr[i][j][0]); idx[j][i] = solver.m - 1; } int c = compute_c(); int c2 = -1; for(int i = 0; i < n; i++) for(int j = i+1; j < n; j++) if(!gr[i][j].empty()) { int& e1 = solver.edges[idx[i][j]].dist; int& e2 = solver.edges[idx[j][i]].dist; if(gr[i][j].size() == 1) e1 = e2 = -1; else e1 = e2 = gr[i][j][1]; // 大二短边 c2 = max(c2, compute_newc(i, j)); e1 = e2 = gr[i][j][0]; // 恢复 } printf("%d %d\n", c, c2); } return 0; }
相关文章推荐
- 最短路模板(Dijkstra & Dijkstra算法+堆优化 & bellman_ford & 单源最短路SPFA)
- POJ 1511 Invitation Cards(单源最短路,优先队列优化的Dijkstra)
- HDU 2544 最短路(单源最短路 dijkstra / floyd / dijkstra(堆优化)/dijkstra+邻接链表+堆优化)
- Dijkstra,最短路树(战争和物流,LA 4080)
- LA 4080 Warfare And Logistics 战争和物流 dijkstra 最短路树
- aoj-2249 Road Construction 单源最短路dijkstra+堆优化(模板)
- 最短路练习10/poj/1511 Invitation Cards ,(两次spfa),(单源最短路,优先队列优化的Dijkstra)
- POJ 3268 Silver Cow Party(dijkstra求单源最短路)
- 昂贵的聘礼 POJ - 1062 单源最短路 Dijkstra
- uva 11374 最短路+记录路径 好题 dijkstra优先队列优化算法 邻接表法 可做模板 G++提交
- B - Flowery Trails Gym - 100783B 堆优化最短路 单源到各个点最短路
- hdu1874 单源最短路Dijkstra
- HOJ 1653 Heavy Transportation&& HOJ 1460 Heavy Cargo (Dijkstra 单源最短路)
- 循环队列+堆优化dijkstra最短路 BZOJ 4152: [AMPPZ2014]The Captain
- 利用分支限界法求解单源最短路(Dijkstra)问题
- LA 4080 战争和物流(最短路树)
- Dijkstra求单源最短路模板
- POJ - 3268 Silver Cow Party解题报告(dijkstra分别求单源起点和单源终点的最短路)
- 图论;单源最短路径;拓扑排序+松弛(有向无回路);Bellman-Ford(回路,负权回路);Dijkstra(无负权,可回路);可以用最小堆实现算法的优化;
- HDU ~ 2544 ~ 最短路 (Dijkstra模板,常规版 and 优先队列优化版)