Codeforces ~ 1076D ~ Edge Deletion (最短路,堆优化理解)

Codeforces ~ 1076D ~ Edge Deletion (最短路,堆优化理解)
文章图片

题意 【Codeforces ~ 1076D ~ Edge Deletion (最短路,堆优化理解)】给你一个n个点,m条边的DAG图,边为双向边,没有重边。现在最多保留k条边,怎么使得好点个数最多。
好点定义为:在原图中1到该点距离和只保留某一些边后的图中1到该点距离不变的点。
先输出保留边的个数,然后输出这些保留的边的编号(1~m)。
思路 堆优化dijkstra中,更新前 k 个点用到的边就是答案。
数据比较大,注意开long long

#include using namespace std; const int MAXN = 3e5+5; typedef long long LL; const LL INF = 0x3f3f3f3f3f3f3f3f; struct Edge { int from, to; LL dist; //起点,终点,距离 Edge(int from, int to, LL dist):from(from), to(to), dist(dist) {} }; struct Dijkstra { int n, m; //结点数,边数(包括反向弧) vector edges; //边表。edges[e]和edges[e^1]互为反向弧 vector G[MAXN]; //邻接表,G[i][j]表示结点i的第j条边在edges数组中的序号 int vis[MAXN]; //标记数组 LL d[MAXN]; //s到各个点的最短路 int p[MAXN]; //上一条弧void init(int n) { this->n = n; edges.clear(); for (int i = 0; i <= n; i++) G[i].clear(); }void AddEdge(int from, int to, int dist) { edges.emplace_back(from, to, dist); m = edges.size(); G[from].push_back(m - 1); }struct HeapNode { int from; LL dist; bool operator < (const HeapNode& rhs) const { return rhs.dist < dist; } HeapNode(int u, LL w): from(u), dist(w) {} }; void dijkstra(int s, vector& ans, int k) { priority_queue Q; for (int i = 0; i <= n; i++) d[i] = INF; memset(vis, 0, sizeof(vis)); d[s] = 0; Q.push(HeapNode(s, 0)); while (!Q.empty() && ans.size() <= k) { HeapNode x = Q.top(); Q.pop(); int u = x.from; if (vis[u]) continue; vis[u] = true; ans.push_back(p[u]/2); 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(e.to, d[e.to])); } } } } }gao; int n, m, k; int vis[MAXN]; int main() { scanf("%d%d%d", &n, &m, &k); memset(vis, 0, sizeof(vis)); gao.init(n); while (m--) { int x, y, w; scanf("%d%d%d", &x, &y, &w); gao.AddEdge(x, y, w); gao.AddEdge(y, x, w); } vector ans; gao.dijkstra(1, ans, k); printf("%d\n", ans.size()-1); for (int i = 1; i < ans.size(); i++) printf("%d%c", ans[i]+1, i==ans.size()-1?'\n':' '); return 0; }

    推荐阅读