[CF1076D] Edge Deletion - Dijkstra,最短路径树

Posted mollnn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF1076D] Edge Deletion - Dijkstra,最短路径树相关的知识,希望对你有一定的参考价值。

给定无向带权连通图,保留至多 (k) 条边,最大化到 (1) 号节点最短路长度不变的点的数量。

Solution

一个显然的做法是,构建原图的一棵最短路径树,任意选择一个大小为 (k) 的包含根的连通块就是答案

另一方面,我们回归到 Dijkstra 算法的原理,不难发现,我们只需要在算法加了 (k) 条边以后停止,当前选择的边集就是答案

#include <bits/stdc++.h>
using namespace std;
#define reset3f(x) memset(x,0x3f,sizeof x)
#define int long long
const int N = 1000005;

int n,m,k,t1,t2,t3;
struct pii {
    int first,second,third;
};
map<int,int> mp;
namespace sp {
const int N=1e+6+5;
vector<pii> g[N];
int n,v0=1,d[N],pre[N];
void make(int t1,int t2,int t3,int t4) {
    g[t1].push_back({t2,t3,t4});
    g[t2].push_back({t1,t3,t4});
}
void reset_graph() {
    for(int i=0;i<=n;i++) g[i].clear();
}
void solve() {
    priority_queue<pair<int,int> > qu;
    reset3f(d);
    d[v0]=0;
    qu.push(make_pair(0,v0));
    while(qu.size()) {
        int p=qu.top().second,r=qu.top().first;
        qu.pop();
        if(r+d[p]) continue;
        if(pre[p]) mp[pre[p]]++;
        if(mp.size()>=k) {
            for(auto i=mp.begin();i!=mp.end();i++)
                cout<<i->first<<" ";
            exit(0);
        }
        for(int i=0;i<g[p].size();i++) {
            int q=g[p][i].first,w=g[p][i].second;
            if(d[q]>d[p]+w) {
                d[q]=d[p]+w;
                qu.push(make_pair(-d[q],q));
                pre[q]=g[p][i].third;
            }
        }
    }
}
}

signed main() {
    ios::sync_with_stdio(false);
    cin>>n>>m>>k;
    k=min(k,n-1);
    cout<<k<<endl;
    for(int i=1;i<=m;i++) {
        cin>>t1>>t2>>t3;
        sp::make(t1,t2,t3,i);
    }
    sp::solve();
}

以上是关于[CF1076D] Edge Deletion - Dijkstra,最短路径树的主要内容,如果未能解决你的问题,请参考以下文章

[CF1076D] Edge Deletion - Dijkstra,最短路径树

cf1076d 贪心最短路

CF1076DEdge Deletion 最短路+贪心

Educational Codeforces Round 54 (Rated for Div. 2) D Edge Deletion (SPFA + bfs)

「CF827D Best Edge Weight」 - LCT

[CF 827D] Best Edge Wight