题目链接:传送门
题目:
D. Edge Deletion time limit per test 2.5 seconds memory limit per test 256 megabytes input standard input output standard output You are given an undirected connected weighted graph consisting of n vertices and m edges. Let's denote the length of the shortest path from vertex 1 to vertex i as di . You have to erase some edges of the graph so that at most k edges remain. Let's call a vertex i good if there still exists a path from 1 to i with length di after erasing the edges. Your goal is to erase the edges in such a way that the number of good vertices is maximized. Input The first line contains three integers n , m and k (2≤n≤3⋅105, 1≤m≤3⋅105, n−1≤m, 0≤k≤m ) — the number of vertices and edges in the graph, and the maximum number of edges that can be retained in the graph, respectively. Then m lines follow, each containing three integers x, y, w (1≤x,y≤n, x≠y, 1≤w≤109), denoting an edge connecting vertices x and y and having weight w . The given graph is connected (any vertex can be reached from any other vertex) and simple (there are no self-loops, and for each unordered pair of vertices there exists at most one edge connecting these vertices). Output In the first line print e — the number of edges that should remain in the graph (0≤e≤k ). In the second line print e distinct integers from 1 to m — the indices of edges that should remain in the graph. Edges are numbered in the same order they are given in the input. The number of good vertices should be as large as possible. Examples Input Copy 3 3 2 1 2 1 3 2 1 1 3 3 Output Copy 2 1 2 Input Copy 4 5 2 4 1 8 2 4 1 2 1 3 3 4 9 3 1 5 Output Copy 2 3 2
题目大意:
一个图N个点M条双向边。设各点到点1的距离为di,保证满足条件删除M-K条边之后使得到点1的距离仍为di的点数量最多的情况下,输出剩余的K条边的编号(按输入顺序)。
(2≤n≤3⋅105, 1≤m≤3⋅105, n−1≤m, 0≤k≤m)
思路:
用dijkstra跑出最短路树:
松弛的时候用fat数组保存被松弛的点的父节点,用faEdge数组保存对应的边,这样就把整棵树保留下来了。
然后在树上bfs,贪心地保留边就好了。(dfs、bfs都可以,反正是树,多一条边就多一个点)
代码:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAX_N = 3e5 + 5; int N, M, K; struct PQNode{ int v; ll dis; PQNode(int _v = 0, ll _dis = 0) : v(_v), dis(_dis) {} bool operator < (const PQNode& x) const { return dis > x.dis; } }; struct Edge{ int id, v; ll w; Edge(int _id = 0, int _v = 0, ll _w = 0) : id(_id), v(_v), w(_w) {} }; vector <Edge> E[MAX_N]; void addEdge(int i, int u, int v, ll w) { E[u].push_back(Edge(i, v, w)); E[v].push_back(Edge(i, u, w)); } bool vis[MAX_N]; ll dist[MAX_N]; int fat[MAX_N], faEdge[MAX_N]; priority_queue <PQNode> PQ; void Dijkstra() { memset(dist, 0x3f, sizeof dist); memset(vis, false, sizeof vis); dist[1] = 0; fat[1] = 1; PQ.push(PQNode(1, 0)); while (!PQ.empty()) { int u = PQ.top().v; PQ.pop(); if (vis[u]) continue; vis[u] = true; for (int i = 0; i < (int)E[u].size(); i++) { int id = E[u][i].id; int v = E[u][i].v; ll w = E[u][i].w; if (vis[v]) continue; if (dist[v] > dist[u] + w) { dist[v] = dist[u] + w; fat[v] = u; faEdge[v] = id; PQ.push(PQNode(v, dist[v])); } } } } vector <int> son[MAX_N]; queue <int> BQ; vector <int> ans; void bfs() { BQ.push(1); while (!BQ.empty() && K > 0) { int u = BQ.front(); BQ.pop(); for (int i = 0; i < (int)son[u].size(); i++) { int v = son[u][i]; if (K > 0) { ans.push_back(faEdge[v]); BQ.push(v); K--; } else break; } } } int main() { cin >> N >> M >> K; for (int i = 1; i <= M; i++) { int u, v; ll w; scanf("%d%d%lld", &u, &v, &w); addEdge(i, u, v, w); } Dijkstra(); for (int i = 2; i <= N; i++) son[fat[i]].push_back(i); bfs(); cout << ans.size() << endl; bool firstprint = true; for (int i = 0; i < (int)ans.size(); i++) { if (firstprint) firstprint = false; else printf(" "); printf("%d", ans[i]); } puts(""); return 0; } /* 3 3 2 1 2 1 3 2 1 1 3 3 */
比赛代码:(改的模板,所以写的有点乱,待我回去整理一下)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const ll INF = 0x3f3f3f3f3f3f3f3f; const int maxn = 3e5 + 5; struct qnode{ int v; ll c; int cnt; qnode(int _v = 0, ll _c = 0, int _cnt = 0) : v(_v), c(_c), cnt(_cnt) {} bool operator < (const qnode& r) const { if (c == r.c) return cnt > r.cnt; return c > r.c; } }; struct Edge{ int v; int id; ll cost; Edge(int _v = 0, int _id = 0, ll _cost = 0) : v(_v), id(_id), cost(_cost) {} }; vector <Edge> E[maxn]; bool vis[maxn]; ll dist[maxn]; int cnt[maxn]; int fa[maxn], faedge[maxn]; //点的编号从 1 开始 void Dijkstra(int N) { memset(vis, false, sizeof (vis)); for (int i = 1; i <= N; i++) dist[i] = INF, cnt[i] = maxn; priority_queue <qnode> Q; dist[1] = 0; cnt[1] = 0; fa[1] = 1; Q.push(qnode(1, 0)); qnode tmp; while (!Q.empty()) { tmp = Q.top(); Q.pop(); int u = tmp.v; if (vis[u]) continue; vis[u] = true; for (int i = 0; i < (int)E[u].size(); i++) { int v = E[u][i].v; ll cost = E[u][i].cost; int id = E[u][i].id; if (!vis[v]) { if (dist[v] > dist[u] + cost) { dist[v] = dist[u] + cost; cnt[v] = cnt[u] + 1; fa[v] = u; faedge[v] = id; Q.push(qnode(v, dist[v], cnt[v])); } else if (dist[v] == dist[u] + cost && cnt[v] > cnt[u] + 1) { cnt[v] = cnt[u] + 1; fa[v] = u; faedge[v] = id; Q.push(qnode(v, dist[v], cnt[v])); } } } } } void addedge(int u, int v, ll w, int i) { E[u].push_back(Edge(v, i, w)); E[v].push_back(Edge(u, i, w)); } int N, M, K; vector <int> son[maxn]; queue <int> BQ; vector <int> ans; void bfs() { BQ.push(1); while (!BQ.empty() && K > 0) { int u = BQ.front(); BQ.pop(); int len = son[u].size(); for (int i = 0; i < len; i++) { int v = son[u][i]; if (K > 0) { K--; ans.push_back(faedge[v]); BQ.push(v); } else break; } } } int main() { cin >> N >> M >> K; for (int i = 1; i <= M; i++) { int u, v; ll w; scanf("%d%d%lld", &u, &v, &w); addedge(u, v, w, i); } Dijkstra(N); for (int i = 2; i <= N; i++) { son[fa[i]].push_back(i); } bfs(); int len = ans.size(); cout << len << endl; bool firstprint = true; for (int i = 0; i < len; i++) { if (firstprint) firstprint = false; else printf(" "); printf("%d", ans[i]); } puts(""); return 0; }