D93 最短路径树 Dijkstra 算法 CF1076D Edge Deletion
D93 最短路径树 Dijkstra 算法 CF1076D Edge Deletion_哔哩哔哩_bilibili
给一个 n 个点, m 条边的无向简单带权连通图, 要求删边至最多剩余 k 条边.
定义"好点"是指删边后, 1 号节点到它的最短路长度仍然等于原图最短路长度的节点.
最大化删边后的好点个数.
思路
我们发现 好点 的定义就是最短路径树上的点
Dijkstra 后,只要从 1 号节点出发,DFS 遍历 min(n,k+1) 个节点,就可以保证找出与 1 连通的且在最短路径树上的 k 个点啦
图中粗边表示以 1 为根的最短路径树的边,如果 k=2,那么 DFS 出边 (1,2) (2,4) 或边 (1,3) (1,2) 就终止即可

相关板子:
D92【模板】最短路径树 Dijkstra 算法 CF545E Paths and Trees - 董晓 - 博客园
// 最短路树 dijkstra 算法 O(MlogN) #include<bits/stdc++.h> #define int long long #define pii pair<int,int> using namespace std; const int N=3e5+5; int h[N],to[N<<1],ww[N<<1],ne[N<<1],idx; void add(int u,int v,int w){ to[++idx]=v;ww[idx]=w;ne[idx]=h[u];h[u]=idx; } int n,m,k,sum,d[N],pre[N]; bool vis[N]; void dijkstra(int s){ memset(d,0x3f,sizeof(d)); d[s]=0; priority_queue <pii,vector<pii>,greater<pii> > q; q.push({0,s}); while(!q.empty()){ int u=q.top().second;q.pop(); if(vis[u])continue; vis[u]=1; for(int i=h[u];i;i=ne[i]){ int v=to[i],w=ww[i]; if(d[v]>=d[u]+w){ d[v]=d[u]+w; pre[v]=i; //保存前驱边 q.push({d[v],v}); } } } } void dfs(int u,int fa){ //输出与根节点相连的最短路径树上的k条边 if(sum==k) exit(0); for(int i=h[u]; i; i=ne[i]){ int v=to[i]; if(v==fa) continue; if(pre[v]==i){ ++sum; printf("%lld ",(i+1)/2); dfs(v,u); } } } signed main(){ scanf("%lld%lld%lld",&n,&m,&k); for(int i=1,a,b,c; i<=m; ++i){ scanf("%lld%lld%lld",&a,&b,&c); add(a,b,c),add(b,a,c); } dijkstra(1); printf("%lld\n",min(n-1,k)); dfs(1,0); }
浙公网安备 33010602011771号