1. 程式人生 > >Codeforces ~ 1076D ~ Edge Deletion (最短路,堆優化理解)

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

在這裡插入圖片描述

題意

給你一個n個點,m條邊的DAG圖,邊為雙向邊,沒有重邊。現在最多保留k條邊,怎麼使得好點個數最多。 好點定義為:在原圖中1到該點距離和只保留某一些邊後的圖中1到該點距離不變的點。 先輸出保留邊的個數,然後輸出這些保留的邊的編號(1~m)。

思路

堆優化dijkstra中,更新前 k 個點用到的邊就是答案。 資料比較大,注意開long long

#include<bits/stdc++.h>
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<Edge> edges; //邊表。edges[e]和edges[e^1]互為反向弧 vector<int> 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<int>& ans, int k) { priority_queue<HeapNode> 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<int> 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; }