题解 CF1076D Edge Deletion

题目链接

既然题目让我们求保留 k 条边的最大好点数量,那我们首先思考这样的问题:什么情况下删一条边必定会删一个点。

显然,只有树才会出现这样的情况,而在一个连通图还没有删成树之前,删边对于点的数量是没有影响的。所以,我们考虑取原图中的一棵树,在树的基础上进行处理。

按照题目,我们应保证:树上的每个节点到 1 号节点的距离是最短路径长度,这时我们引入最短路径树(SPT)的概念。

dijkstra 求最短路(边权 0)的过程中,由于每个点只会遍历一次,所以自然就形成了一棵树。对于每个节点,记录使得其取最小值的边,如果有几条边都能使其取最短路,那么依题目具体而定(如Paths and Trees,同等情况取最小边)。

按照 dij 建出 SPT 以后,从下往上进行删边,这样可以保证每次删一个点,类似于拓扑排序的过程做一遍即可。

点击查看代码
#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&&deg[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;
}
posted @   2017BeiJiang  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示