CF1494F Delete The Edges 题解

news2024/9/24 0:28:07

Description

给定一张 n n n 个点、 m m m 条边的图,你可以从图上任意一点出发,目标是删去所有的边,当一条边被删去后你不能再走此边。

初始模式下,一条边在你走过后会立即被删去。

你可以在任意一点切换模式(或全程不换),换完模式后走过的第偶数条便会被删去,且不可重新换回初始模式。

求一组方案。

Solution

观察样例可得切换模式后走的图为一个菊花图,下面浅浅分析一下。

假设只有一条边,则折返走一遍便能删完。

若为两条边 ( i , j ) , ( j , k ) (i,j),(j,k) (i,j),(j,k),发现只能 j → i → j → k → j j\rightarrow i\rightarrow j\rightarrow k\rightarrow j jijkj 将其删完。

依此类推,删边必须像 i → j → i i\rightarrow j\rightarrow i iji 折返地删。

所以我们可以枚举菊花图的中心,构造出走一条终点为菊花图中心的欧拉路径,然后切换模式的方案。

关键在于如何求出这条欧拉路径。

首先将所有和中心相连的奇点(度数为奇)和中心连的这条边删去,这样这个点就会变为偶点(度数为偶),方便后续操作。

然后得出当前图中奇点个数 c n t cnt cnt,和中心度数是否为 0 0 0,记为 f f f

f = t r u e f=true f=true

  • c n t > 2 cnt>2 cnt>2,无法构出欧拉路径,非法。

  • c n t = 2 cnt=2 cnt=2 且中心不为奇点,终点不为中心,非法。

  • c n t = 2 cnt=2 cnt=2 且外围图不连通(除去度数为 0 0 0 的点,这些点虽然不连通,但切换模式后都会连通),非法。

  • c n t = 2 cnt=2 cnt=2 且外围连通,即我们已经构造出了合法方案。

f = f a l s e f=false f=false

  • c n t ≥ 2 cnt\ge2 cnt2,还要连一条边到中心,然而再加边就不是欧拉路径了,非法。

剩下还剩当前路径有中心但外围不连通、当前路径不含中心两种情况,发现 c n t = 0 cnt=0 cnt=0 使得我们可以在加一条删去的边到欧拉路径上,那我们就枚举这条边。

首先当前外围图(此时是除去度数为 0 0 0 的点但此点不为中心)连通块个数要小于等于 2 2 2,因为加一条边只能让两个连通块连通。

然后分别将这两连通块染色,遍历删去的边,若边的两顶点颜色不同,则加上这条边,发现这种合法方案的起点就是这两顶点中不是中心的那个点。

发现一定存在这条先前被删去的边,即我们一定能找到合法方案。

然后我们按输出要求输出方案即可,首先遍历欧拉路径,再切换模式,然后折返删菊花图。

代码细节很多,理清思路再写。

时间复杂度 O ( n ( n + m ) ) O(n(n+m)) O(n(n+m))

Code

#include<bits/stdc++.h>
using namespace std;
int n,m;
int tot,head[3030];
int in[3030],du[3030],col[3030];
bool vis[3030],viss[3030],pit[3030];
vector<int> path;
struct edge{
	int to,next,id;
}e[6060];
void add(int x,int y,int z){
	e[++tot]=edge{y,head[x],z};
	head[x]=tot;
}
void dfs(int x,int v=0){
	viss[x]=1;
	col[x]=v;
	for(int i=head[x];i;i=e[i].next){
		int y=e[i].to,w=e[i].id;
		if(viss[y]||vis[w]) continue;
		dfs(y,v);
	}
}
void get(int x){
	bool f=0;
	int ss,ww;
	for(int i=head[x];i;i=e[i].next){
		int y=e[i].to,w=e[i].id;
		if(!vis[w]){
			vis[w]=1;
			get(y);
			path.push_back(x);
		}
	}
}
bool solve(int st){
	for(int i=1;i<=n;i++) du[i]=in[i],viss[i]=0,pit[i]=0,col[i]=0;
	for(int i=1;i<=m;i++) vis[i]=0;
	bool f=0;
	int ts=0,ttot=0;  //ts为方案起点、ttot为切换模式后删的边数
	for(int i=head[st];i;i=e[i].next){
		int y=e[i].to,w=e[i].id;
		if(du[y]%2){  //删去中心与偶点相连的边
			pit[y]=1,du[y]--,du[st]--,vis[w]=1,ttot++;
		}else f=1;  //中心是否在当前欧拉路径上
	}
	int cnt=0,fl=0;
	for(int i=1;i<=n;i++){
		if(du[i]%2) cnt++;  //奇点数量
		if(du[i]%2&&i!=st) fl=i;  //得出合法欧拉路径的起点
	}
	if(f){
		if(fl==0) fl=st;  //欧拉回路则任选起点
		if(cnt>2) return 0;
		if(cnt==2&&du[st]%2==0) return 0;
		if(cnt==2){
			dfs(st);
			for(int i=1;i<=n;i++){  //判断外围连通性
				if(du[i]==0) continue;
				if(!viss[i]) return 0;
			}
			ts=fl;
		}
		
	}else{
		if(cnt>=2) return 0;
	}
	if(cnt==0){
		dfs(st);  //染第一个连通块
		bool ff=0;
		for(int i=1;i<=n;i++){
			if(du[i]==0) continue;
			if(!viss[i]){
				if(ff) return 0;  //有至少三个连通块
				dfs(i,1);
				ff=1;
			}
		}
		if(ff){
			for(int i=head[st];i;i=e[i].next){
				int y=e[i].to,w=e[i].id;
				if(pit[y]&&col[y]){  //是之前删去的奇点且与中心不在同一连通块上
					pit[y]=0,vis[w]=0,ttot--;
					ts=y,du[y]++,du[st]++;
					break;
				}
			}
		}else{  //只有一个连通块即为欧拉回路
			ts=st;
		}
	}
	cout<<m+ttot+2<<'\n';  //m条边要删完则有m次操作,ttot条边被操作2次,加上起点和切换模式的2次操作
	get(ts);  //遍历欧拉路径
	for(int i=path.size()-1;i>=0;i--) cout<<path[i]<<" ";
	cout<<st<<" ";
	cout<<-1<<" ";
	for(int i=head[st];i;i=e[i].next){
		int y=e[i].to,w=e[i].id;
		if(pit[y]){
			cout<<y<<" "<<st<<" ";  //折返删菊花图
		}
	}
	return 1;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(nullptr);
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		in[x]++,in[y]++;
		add(x,y,i),add(y,x,i);
	}
	for(int i=1;i<=n;i++){
		if(solve(i)){
			return 0;
		}
	}
	cout<<"0"<<'\n';  //无解
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2158885.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

前端-js例子:todolist

实现效果图&#xff1a; 实现步骤&#xff1a; 1.body部分 1.首先&#xff0c;设置输入数据的框和按钮进行操作 2.设置一个表格标签&#xff08;有边框&#xff09;&#xff0c;首先在表头放置两列&#xff08;“事项”‘’操作&#xff09; <body><div class"…

初学者怎么入门大语言模型(LLM)?看完这篇你就懂了!

当前2024年&#xff0c;LLM领域发展日新月异&#xff0c;很多新的实用技术层出不穷&#xff0c;个人认为要跟上LLM的发展&#xff0c;需要掌握以下内容&#xff0c;并需要不断地跟踪学习。 入门LLM前置基础 深度学习基础知识&#xff1a;推荐李宏毅的深度学习课程Python和num…

数据结构2——单链表

目录 1.链表 1.1链表的概念及结构 1.2 链表的分类 ​编辑2.无头单链表的实现 1. 节点 2.遍历链表 3.动态增加新节点 4.查找&#xff08;修改&#xff09; 5.插入 5.1 尾插 5.2 头插 5.3 在pos之前插入x 5.4 在pos之后插入x 6.删除 6.1 尾删 6.2 头删 6.3 删除…

DPDK 简易应用开发之路 4:基于Pipeline模型的DNS服务器

本机环境为 Ubuntu20.04 &#xff0c;dpdk-stable-20.11.10 使用scapy和wireshark发包抓包分析结果 完整代码见&#xff1a;github Pipeline模型 DPDK Pipeline模型是基于Data Plane Development Kit&#xff08;DPDK&#xff09;的高性能数据包处理框架。它通过将数据流分为多…

基于SpringBoot+Vue+MySQL的旅游推荐管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 随着社会的快速发展和人民生活水平的显著提高&#xff0c;旅游已成为人们休闲娱乐的重要方式。然而&#xff0c;面对海量的旅游信息和多样化的旅游需求&#xff0c;如何高效地管理和推荐旅游资源成为了一个亟待解决的问题。因此…

学习记录:js算法(四十三):翻转二叉树

文章目录 翻转二叉树我的思路网上思路递归栈 总结 翻转二叉树 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点 图一&#xff1a; 图二&#xff1a; 示例 1&#xff1a;&#xff08;如图一&#xff09; 输入&#xff1a;root [4,2,7,1…

大模型价格战,打到了负毛利,卷or不卷?

国产大模型淘汰赛在加速。这轮淘汰赛会持续一两年&#xff0c;只有少数真正具备实力的基础模型企业能继续活下去 中国市场的大模型价格战已经打了近半年。这轮价格战已经打到了负毛利&#xff0c;而且暂时没有停止迹象。头部云厂商仍在酝酿新一轮降价。这轮降价会在今年9月下旬…

视频单目标跟踪研究

由于对视频单目标跟踪并不是很熟悉&#xff0c;所以首先得对该领域有个大致的了解。 视频目标跟踪是计算机视觉领域重要的基础性研究问题之一&#xff0c;是指在视频序列第一帧指定目标 后&#xff0c;在后续帧持续跟踪目标&#xff0c;即利用边界框&#xff08;通常用矩形框表…

printf 命令:格式化输出

一、命令简介 ​printf​ 命令在 Linux 系统中用于格式化并打印字符串到标准输出。它是 C 语言中 printf ​函数的命令行版本&#xff0c;因此其格式化选项与 C 语言中的非常相似。 相关命令&#xff1a; echo&#xff1a;通常使用 echo&#xff0c;它比较简单。printf&…

你们用过微信CRM管理系统吗?

微信CRM管理系统是近年来流行的管理软件&#xff0c;在市场上得到了很高的认可。许多企业正在应用微信CRM管理系统&#xff0c;那系统具体有些什么功能呢&#xff1f; 1、聚合聊天&#xff0c;可以管理多个微信号 2、批量多号自动加好友任务&#xff0c;设置好时间间隔以及加人…

《论软件系统架构风格》写作框架,软考高级系统架构设计师

论文真题 系统架构风格&#xff08;System Architecture Style&#xff09;是描述某一特定应用领域中系统组织方式的惯用模式。架构风格定义了一个词汇表和一组约束&#xff0c;词汇表中包含一些构件和连接件类型&#xff0c;而这组约束指出系统是如何将这些构件和连接件组合起…

李沐对大模型趋势的几点判断,小模型爆发了!

李沐是上海交通大学 2011 届计算机科学与工程系本硕系友。他曾担任亚马逊资深首席科学家&#xff0c;加州大学伯克利分校和斯坦福大学的访问助理教授&#xff0c;是前 Marianas Labs 联合创始人&#xff0c;深度学习框架 Apache MXNet 的创始人之一。目前是 BosonAI 联合创始人…

C++之STL—string容器

本质&#xff1a;类 class 封装了很多方法&#xff1a;查找find&#xff0c;拷贝copy&#xff0c;删除delete 替换replace&#xff0c;插入insert 构造函数 赋值操作 assign&#xff1a; 字符串拼接 &#xff0b; append&#xff1a; string查找和替换 没查找到&#xff0c;po…

【刷题2—滑动窗口】最大连续1的个数lll、将x减到0的最小操作数

目录 一、最大连续1的个数lll二、将x减到0的最小操作数 一、最大连续1的个数lll 题目&#xff1a; 思路&#xff1a; 问题转换为&#xff1a;找到一个最长子数组&#xff0c;这个数组里面0的个数不能超过k个 定义一个变量count&#xff0c;来记录0的个数&#xff0c;进窗口、…

时序预测 | Python实现KAN+LSTM时间序列预测

时序预测 | Python实现KAN+LSTM时间序列预测 目录 时序预测 | Python实现KAN+LSTM时间序列预测预测效果基本介绍程序设计预测效果 基本介绍 时序预测 | KAN+LSTM时间序列预测(Python) KAN作为这两年最新提出的机制,目前很少人用,很适合作为时间序列预测的创新点,可以结合…

【重学 MySQL】三十八、group by的使用

【重学 MySQL】三十八、group by的使用 基本语法示例示例 1: 计算每个部门的员工数示例 2: 计算每个部门的平均工资示例 3: 结合 WHERE 子句 WITH ROLLUP基本用法示例注意事项 注意事项 GROUP BY 是 SQL 中一个非常重要的子句&#xff0c;它通常与聚合函数&#xff08;如 COUNT…

MySQL和SQL的区别简单了解和分析使用以及个人总结

MySQL的基本了解 运行环境&#xff0c;这是一种后台运行的服务&#xff0c;想要使用必须打开后台服务&#xff0c;这个后台服务启动的名字是在安装中定义的如下图&#xff08;个人定义MySQL88&#xff09;区分大小写图片来源 可以使用命令net start/stop 服务名&#xff0c;开…

实验十八:IIC-EEPROM实验

这个实验比较复杂,是目前第一个多文件项目 KEY1-4:P3^0-P3^3 IIC_SCL=P2^1; IIC_SDA=P2^0; //定义数码管位选信号控制脚 LSA=P2^2; LSB=P2^3; LSC=P2^4; 代码 main.c #include "public.h" #in

常见汽车零部件ASIL等级示例

ASIL&#xff08;Automotive Safety Integrity Level&#xff0c;汽车安全完整性等级&#xff09;评级系统是ISO 26262标准中定义的一套风险分类体系&#xff0c;用于评估道路车辆中电子电气系统&#xff08;E/E系统&#xff09;功能安全的风险程度&#xff0c;并确保这些系统在…

Linux相关概念和重要知识点(6)(make、makefile、gdb)

1.make、makefile &#xff08;1&#xff09;什么是make、makefile&#xff1f; 在我们写完代码后&#xff0c;要编译运行&#xff0c;如果有多个.c文件就需要每次都自己用gcc -o来处理&#xff0c;这十分麻烦。当我们想要自定义多个文件的处理时&#xff0c;我们会浪费很多时…