CF1076D Edge Deletion
Posted excellent-zzy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1076D Edge Deletion相关的知识,希望对你有一定的参考价值。
题目大意:给定 N 个点 M 条边的无向简单联通图,留下最多 K 条边,求剩下的点里面从 1 号顶点到其余各点最短路大小等于原先最短路大小的点最多怎么构造。
这个题贪心+dijkstra
我们可以在第一次跑 dij 时直接采用贪心策略,即:若当前答案集合的大小小于 K 且优先队列非空,则继续优先队列遍历,每次把一条边加入到答案集合中。
因为是在求解最短路过程中向答案集合中加边,可知这就是一种最优策略。
#define B cout << "BreakPoint" << endl;
#define O(x) cout << #x << " " << x << endl;
#define O_(x) cout << #x << " " << x << " ";
#define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
#define LL long long
const int inf = 1e9 + 9;
const int N = 5e5 + 5;
using namespace std;
inline int read() {
int s = 0,w = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {
if(ch == '-')
w = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9') {
s = s * 10 + ch - '0';
ch = getchar();
}
return s * w;
}
typedef pair<LL,int> pii;
struct node{
int nxt,to,w;
}e[N<<1];
int head[N],n,m,k,pre[N],vis[N],tot = 1;
inline void add(int x,int y,int w){
e[++tot] = node{head[x],y,w},head[x] = tot;
}
LL dis[N];
vector<int> ans;
priority_queue<pii> q;
void init(){
n = read(),m = read(),k = read();
for(int i = 1;i <= m;i++){
int x = read(),y = read(),w = read();
add(x,y,w),add(y,x,w);
}
}
void dij(){
for(int i = 2;i <= n;i++) dis[i] = 1e15;
q.push(make_pair(0,1));
while(!q.empty() && ans.size() < k){
int u = q.top().second;
q.pop();
if(vis[u]) continue;
if(u ^ 1) ans.push_back(pre[u] / 2);
vis[u] = 1;
for(int i = head[u];i;i = e[i].nxt){
int v = e[i].to,w = e[i].w;
if(dis[v] > dis[u] + w){
dis[v] = dis[u] + w,pre[v] = i;
q.push(make_pair(-dis[v],v));
}
}
}
}
void solve(){
dij();
k = ans.size();
printf("%d
",k);
for(int i = 0;i < k;i++) printf("%d ",ans[i]);
}
int main(){
init();
solve();
return 0;
}
以上是关于CF1076D Edge Deletion的主要内容,如果未能解决你的问题,请参考以下文章
[CF1076D] Edge Deletion - Dijkstra,最短路径树
Educational Codeforces Round 54 (Rated for Div. 2) D Edge Deletion (SPFA + bfs)