码迷,mamicode.com
首页 > 其他好文 > 详细

CF1076D Edge Deletion

时间:2020-03-03 22:15:35      阅读:68      评论:0      收藏:0      [点我收藏+]

标签:include   type   return   turn   联通图   make   stream   题目   struct   

题目大意:给定 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\n",k);
    for(int i = 0;i < k;i++) printf("%d ",ans[i]);
}
int main(){
    init();
    solve();
    return 0;
}

CF1076D Edge Deletion

标签:include   type   return   turn   联通图   make   stream   题目   struct   

原文地址:https://www.cnblogs.com/excellent-zzy/p/12404923.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!