CodeForces #303E Div.2 Paths and Trees(最短路+拓扑排序)
来源:互联网 发布:高阶矩阵求逆 编辑:程序博客网 时间:2024/05/16 05:45
果然题目写完不抓紧写博客就全部都不记得还得把题目先理一遍。
题目链接:http://codeforces.com/problemset/problem/545/E
题目大意:求给定图的一颗最小最短路生成树,最小最短路生成树满足的条件是以顶点1为根的一棵生成树,从1到所有点的路径长度全是原无向图中的最短路长度,在所有的符合条件的树中找到代价最小的,输出边的编号。
如果单纯考虑求最短路,然后记录路径未必是满足条件,比如edge[1][3] = 2, edge[1][2] = 1, edge[2][3] = 1,这样1到3的距离可以是直接距离,也可以是间接距离。但是如果要代价最小,肯定选择间接距离。
考虑到这种情况,我们先计算最短路,但是不计算更新路径。枚举所有的边,找出所有与最短路的不冲突的入边,并计算同时点的入度。最后用拓扑排序寻找最小代价的邻接边,然后将对应的边加入集合中,然后删去这个顶点。(这个过程需要多想几遍才好理解)。
代码如下:
#include <bits/stdc++.h>using namespace std;typedef long long LL;const LL oo = INT_MAX;const LL maxn = 300005;struct N { int v; LL dis; N(int a, LL b): v(a), dis(b) {} bool operator < (const N& other) const { return dis > other.dis; }};struct E { int to; LL cost; int next;};E edge[2 * maxn];int head[maxn];LL dist[maxn];int vis[maxn];int indeg[maxn];vector<LL> inarr[maxn];LL n, m, s;int eid = 1;vector<LL> arr;void addEdge(int from, int to, int cost) { edge[eid].to = to; edge[eid].cost = cost; edge[eid].next = head[from]; head[from] = eid ++;}void dij(int s) { for (int i = 1; i <= n; i ++) { vis[i] = false; dist[i] = oo; } priority_queue<N> que; dist[s] = 0; que.push(N(s, (LL)0)); while (!que.empty()) { N cur = que.top(); que.pop(); if(vis[cur.v]) { continue; } vis[cur.v] = 1; for (int j = head[cur.v]; ~j; j = edge[j].next) { int e = edge[j].to; if(dist[e] >= edge[j].cost + cur.dis || dist[e] == oo) { dist[e] = edge[j].cost + cur.dis; que.push(N(e, dist[e])); } } }}void topo(int s) { LL ans = 0; queue<int> q; q.push(s); //队列中元素为入度为0的点,这些点的前驱必定已经加入树的集合 while(!q.empty()) { int cur = q.front(); q.pop(); int len = inarr[cur].size(); if(len > 0) { int minEdge = oo, pos = -1; for (int i = 0; i < len; i ++) { int id = inarr[cur][i]; if(minEdge > edge[id].cost) { minEdge = edge[id].cost; pos = id; } } ans += minEdge; arr.push_back((pos + 1) >> 1); } for (int i = head[cur]; ~i; i = edge[i].next) { if(dist[edge[i].to] == dist[cur] + edge[i].cost) { indeg[edge[i].to] --; if(indeg[edge[i].to] == 0) { q.push(edge[i].to); } } } } printf("%I64d\n",ans); int arrlen = arr.size(); for (int i = 0; i < arrlen; i ++) { printf("%I64d ", arr[i]); }}int main() { scanf("%I64d%I64d", &n, &m); int i = 1; int from, to, cost; memset(head, -1, sizeof(head)); while(i <= m) { scanf("%d%d%d", &from, &to, &cost); addEdge(from, to, cost); addEdge(to, from, cost); i ++; } scanf("%I64d", &s); dij(s); for (int i = 1; i <= n; i ++) { for (int j = head[i]; ~j; j = edge[j].next) { if(dist[edge[j].to] == dist[i] + edge[j].cost) { indeg[edge[j].to] ++; //所有点符合最短路的入度 inarr[edge[j].to].push_back(j); //所有点符合最短路的边列表 } } } topo(s); return 0;}
0 0
- CodeForces #303E Div.2 Paths and Trees(最短路+拓扑排序)
- Codeforces Round #303 (Div. 2)E. Paths and Trees 最短路
- Codeforces Round #303 (Div. 2) E. Paths and Trees (最短路+变形最小生成树)
- Codeforces Round #303 (Div. 2) - E. Paths and Trees(最短路)
- CodeForces 545E Paths and Trees(最短路)
- E. Paths and Trees (CF 303 div2)最短路
- Codeforces Round #303 (Div. 2) E. Paths and Trees
- codeforces 545 Round #303 (Div. 2) E Paths and Trees
- Codeforces Round #Pi (Div. 2) E. President and Roads(边双无向图缩点(有重边)+最短路)
- CodeForces 545E Paths and Trees
- codeforces 545 E. Paths and Trees
- Codeforces 545E Paths and Trees
- Codeforces#303-E - Paths and Treesg-最短路+最小生成树
- Codeforces Round #Pi (Div. 2) E. President and Roads (最短路+强连通求割边)
- Codeforces Round #Pi (Div. 2) E. President and Roads 最短路,桥
- 08/13 D -> codeforces Round #Pi div 2 E. President and Roads 最短路变形
- Codeforces Round #287 (Div. 2) E. Breaking Good 最短路
- Codeforces Round #169 (Div. 2) E.Little Girl and Problem on Trees(成段更新)
- BZOJ 2217 Poi2011 Lollipop
- 欢迎使用CSDN-markdown编辑器
- Ruby中的Profiling工具
- Windows下面查看Python帮助
- 引用和指针的区别和联系
- CodeForces #303E Div.2 Paths and Trees(最短路+拓扑排序)
- B. Vanya and Books
- C++|C++学习笔记|五、类
- Linux vim 使用总结
- Thinkphp开发时如何关闭缓存
- 联诚发(LCF)全彩LED显示屏,炫彩耀世界
- Visual C++ Tips: error C2823: a typedef template is illegal
- 第三章
- MySQL timestamp自动更新时间分享