CF-125E MST Company (单度限制最小生成树)
参考红宝书
对除 1 号点顶点外的点集,求一次最小生成森林,对于最小生成森林的联通分量,选择最短的一条边与 1 号点相连。设此时 1 号点的度为 \(k_0\),如果 \(k_0\lt L\) 则无解 (L为1号顶点的规定度)
然后通过可行交换来增加 1 号点的度,每次尝试加入一条和 1 号点相连的边,然后删去所形成的环上面的最长边。
此题点数为 5000,对于每次交换,可以用树形DP求出所有点到 1 号点的最长边。每次选择增量最小的边去交换,直到 \(k_0\) 达到 L
在实现中的一些困难:
- 答案要求构成生成树的边序号,所以加边时要保留原边序号信息
- 树形DP要找到每个点到 根 的最长路大小,以及对应边的序号
- 如果一个点与根直接相连,可以把这个边序号保留下来(下面代码中用path数组保留),方便之后做替换用
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
#define dbg(x...) do { cout << "\033[32;1m" << #x <<" -> "; err(x); } while (0)
void err() { cout << "\033[39;0m" << endl; }
template<class T, class... Ts> void err(const T& arg,const Ts&... args) { cout << arg << " "; err(args...); }
const int N = 5000 + 5;
const int M = 200010;
int head[N], ver[M], nxt[M], edge[M];
int fa[N], mark[M], best[N], cand[N];
int path[N];
int n, m, k, tot;
struct Edge{
int x, y, z;
int id;
Edge(int a=0,int b=0, int c=0, int d=0):x(a),y(b),z(c),id(d){}
bool operator <(Edge b){
return z < b.z;
}
}e[M];
void add(int x, int y, int z, int id){
ver[id] = y, edge[id] = z, nxt[id] = head[x], head[x] = id;
}
void addEdge(int i){
add(e[i].x, e[i].y, e[i].z, i*2);
add(e[i].y, e[i].x, e[i].z, i*2+1);
}
int find(int x){return x == fa[x] ? x : fa[x] = find(fa[x]);}
void dfs(int x, int fat){
for(int i=head[x];i;i=nxt[i]){
if(!mark[i>>1] || ver[i] == fat) continue;
int y = ver[i];
if(x == 1){// 从根出发的边,不能被替换
best[y] = -inf;
} else {
best[y] = edge[i], cand[y] = i >> 1; // 边的序号其实是 i/2
if(best[y] < best[x]){
best[y] = best[x];
cand[y] = cand[x];
}
}
dfs(y, x);
}
}
bool solve(){
sort(e + 1, e + 1 + m);
for(int i=1;i<=n;i++) fa[i] = i;
for(int i=1;i<=m;i++){
int x = e[i].x, y = e[i].y;
if(x == 1 || find(x) == find(y)) continue;
mark[e[i].id] = 1;
fa[find(x)] = find(y);
}
//按照id排序,便于之后处理
sort(e + 1, e + 1 + m, [](Edge a, Edge b){return a.id < b.id;});
int component = 0;//连通块个数
for(int i=2;i<=n;i++){
if(find(i) == i){
component ++;
best[i] = inf;
}
}
if(component > k) return false;
for(int i=1;i<=m;i++){
if(e[i].x != 1) continue;
path[e[i].y] = i;
int rt = find(e[i].y);
if(e[i].z < best[rt]){
best[rt] = e[i].z;
cand[rt] = i;
}
}
for(int i=2;i<=n;i++){
if(find(i) != i) continue;
if(best[i] == inf) return false;
mark[cand[i]] = 1;
}
for(int i=1;i<=m;i++){
if(mark[i]) addEdge(i);
}
while(component < k){
dfs(1, 0); //树形DP
int mx = inf, tcand = 0;
for(int i=2;i<=n;i++){
if(path[i] == 0 || best[i] == -inf) continue;
if(e[path[i]].z - best[i] < mx){
mx = e[path[i]].z - best[i];
tcand = i;
}
}
if(mx == inf) return false;
mark[cand[tcand]] = 0;
mark[path[tcand]] = 1;
addEdge(path[tcand]);
component ++;
}
printf("%d\n", n-1);
for(int i=1;i<=m;i++){
if(mark[i]) printf("%d ", i);
}
return true;
}
int main(){
scanf("%d%d%d", &n, &m, &k);
for(int i=1;i<=m;i++){
int x, y, z;scanf("%d%d%d", &x, &y, &z);
if(x > y) swap(x, y);
e[i] = Edge(x, y, z, i);
}
if(!solve()) puts("-1");
return 0;
}
CF-125E MST Company (单度限制最小生成树)的更多相关文章
- CodeForces 125E MST Company
E. MST Company time limit per test 8 seconds memory limit per test 256 megabytes input standard inpu ...
- CODEFORCES 125E MST Company 巧用Kruskal算法
题意:给定一个带权边无向图,求最小生成树,且满足第一个节点的度为固定的k 无解则输出-1 数据规模: 节点数n和限制k<=5000 边数m<=10^5 时限8sec 思路: 首先时限比较宽 ...
- 【CF125E】MST Company(凸优化,最小生成树)
[CF125E]MST Company(凸优化,最小生成树) 题面 洛谷 CF 题解 第一眼看见就给人丽洁姐那道\(tree\)一样的感觉. 那么二分一个权值,加给所有有一个端点是\(1\)的边, 然 ...
- luogu CF125E MST Company wqs二分 构造
LINK:CF125E MST Company 难点在于构造 前面说到了求最小值 可以二分出斜率k然后进行\(Kruskal\) 然后可以得到最小值.\(mx\)为值域. 得到最小值之后还有一个构造问 ...
- 【AtCoder3611】Tree MST(点分治,最小生成树)
[AtCoder3611]Tree MST(点分治,最小生成树) 题面 AtCoder 洛谷 给定一棵\(n\)个节点的树,现有有一张完全图,两点\(x,y\)之间的边长为\(w[x]+w[y]+di ...
- CF F. MST Unification (最小生成树避圈法)
题意 给一个无向加权联通图,没有重边和环.在这个图中可能存在多个最小生成树(MST),你可以进行以下操作:选择某条边使其权值加一,使得MST权值不变且唯一.求最少的操作次数. 分系:首先我们先要知道为 ...
- 度限制最小生成树 POJ 1639 贪心+DFS+prim
很好的解题报告: http://blog.csdn.net/new_c_yuer/article/details/6365689 注意两点: 1.预处理环中权值最大的边···· 2.可以把去掉度限制后 ...
- POJ 1679 The Unique MST (次小生成树 判断最小生成树是否唯一)
题目链接 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. De ...
- Solution -「CF 1025G」Company Acquisitions
\(\mathcal{Description}\) Link. \(n\) 个公司,每个公司可能独立或者附属于另一个公司.初始时,每个公司附属于 \(a_i\)(\(a_i=-1\) 表示该公 ...
随机推荐
- Sentry(v20.12.1) K8S 云原生架构探索,玩转前/后端监控与事件日志大数据分析,高性能+高可用+可扩展+可伸缩集群部署
Sentry 算是目前开源界集错误监控,日志打点上报,事件数据实时分析最好用的软件了,没有之一.将它部署到 Kubernetes,再搭配它本身自带的利用 Clickhouse (大数据实时分析引擎)构 ...
- [Leetcode刷题]——链表
一.找出两个链表的交点 160.相交链表(easy)2021-01-05 编写一个程序,找到两个单链表相交的起始节点 如下面的两个链表,在c1 处相交: public class Soluti ...
- 【Java基础】Java11 新特性
Java11 新特性 新增字符串处理方法 新增方法: 判断字符串是否为空白 " ".isBlank(); // true 去除首尾空白 " Javastack " ...
- 【Maven】Maven 高级应用
Maven 高级应用 Maven 基础 Maven 是一个项目管理工具,它有如下好处: 节省磁盘空间 可以一键构建 可以跨平台使用 依赖传递和管理,提高开发效率 一键构建:Maven 自身集成了 To ...
- Python 日志打印之logging.getLogger源码分析
日志打印之logging.getLogger源码分析 By:授客 QQ:1033553122 #实践环境 WIN 10 Python 3.6.5 #函数说明 logging.getLogger(nam ...
- (一)React Ant Design Pro + .Net5 WebApi:先搞定服务器,顺手装个Nginx
腾讯云搞定服务器,具体过程就不赘述了,文档都有,咨询客服或者自行百度,体验一下过程. 一. 服务器 1. 云服务器 cvm 1核2G centos8.0 2. 域名注册 www.homejok.com ...
- 【ORACLE错误】SP2-0618: Cannot find the Session Identifier. Check PLUSTRACE role is enabled
执行set autotrace traceonly的时候,报错 SQL> set autotrace traceonly SP2-0618: Cannot find the Session Id ...
- 【葵花宝典】kolla部署OpenStack-AllinOne
1.关闭防火墙以及内核安全机制 systemctl stop firewalld systemctl disable firewalld ##永久性关闭 setenforce 0 sed -i 's/ ...
- MySQL全面瓦解19:游标相关
定义 我们经常会遇到这样的一种情况,需要对我们查询的结果进行遍历操作,并对遍历到的每一条数据进行处理,这时候就会使用到游标. 所以:游标(Cursor)是处理数据的一种存储在MySQL服务器上的数据库 ...
- [Ceoi2004]Journey
题目描述 给出N个点,及你的出发点K. 接下来N-1行描述有关边的开始点,结束点,边长.保证图中不会有环 接下来给出数字J,代表你要走多少个点. 接下来J个数字,代表你要走过的点的编号.当然你可以自己 ...