题解 CF1076D Edge Deletion
既然题目让我们求保留 条边的最大好点数量,那我们首先思考这样的问题:什么情况下删一条边必定会删一个点。
显然,只有树才会出现这样的情况,而在一个连通图还没有删成树之前,删边对于点的数量是没有影响的。所以,我们考虑取原图中的一棵树,在树的基础上进行处理。
按照题目,我们应保证:树上的每个节点到 号节点的距离是最短路径长度,这时我们引入最短路径树(SPT)的概念。
在 求最短路(边权 )的过程中,由于每个点只会遍历一次,所以自然就形成了一棵树。对于每个节点,记录使得其取最小值的边,如果有几条边都能使其取最短路,那么依题目具体而定(如Paths and Trees,同等情况取最小边)。
按照 建出 以后,从下往上进行删边,这样可以保证每次删一个点,类似于拓扑排序的过程做一遍即可。
点击查看代码
#include<bits/stdc++.h> using namespace std; typedef long long LL; #define PII pair<LL,int> const int N=1e6+10; int n,m,k; struct node { int to,w,id; }; vector<node> g[N]; LL dis[N]; int vis[N]; int f[N],edge_id[N]; priority_queue<PII> q; void dij(int st) { memset(dis,0x3f,sizeof(dis)); dis[st]=0; q.push({0,st}); while(q.size()) { int x=q.top().second; q.pop(); if(vis[x]) continue; vis[x]=1; for(auto t:g[x]) { int y=t.to,w=t.w,id=t.id; if(vis[y]) continue; if(dis[y]>dis[x]+w) { dis[y]=dis[x]+w; f[edge_id[y]]=0; f[id]=1; edge_id[y]=id; q.push({-dis[y],y}); } } } } int deg[N]; queue<int> qq; int main() { cin>>n>>m>>k; for(int i=1;i<=m;i++) { int u,v,w; cin>>u>>v>>w; g[u].push_back({v,w,i}); g[v].push_back({u,w,i}); } dij(1); for(int i=1;i<=n;i++) { for(auto t:g[i]) { if(!f[t.id]) continue; deg[t.to]++; } } int cut_num=n-1-k; for(int i=1;i<=n;i++) if(i!=1&°[i]==1) qq.push(i); while(qq.size()&&cut_num>0) { int x=qq.front(); qq.pop(); for(auto t:g[x]) { if(!f[t.id]) continue; deg[t.to]--; cut_num--; f[t.id]=0; if(deg[t.to]==1&&t.to!=1) qq.push(t.to); if(!cut_num) break; } } int cnt=0; for(int i=1;i<=m;i++) { if(f[i]) cnt++; } cout<<cnt<<endl; for(int i=1;i<=m;i++) if(f[i]) cout<<i<<' '; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效