CF141E Clearing Up 题解
思路分析
自认为是一道很好的思维题。
直接看上去的想法是:
跑一个生成树,每一次加的边颜色交替进行,直到拉出生成树。
仔细想想,发现可能无法保证最后是一棵树而不是森林,也是说输出都是 \(-1\) 。
然后,我这个弱智就没有任何思路了。
这时,想起“拖帝”的名言:正难则反。于是考虑先筛去不合法的情况。(以下的判断以并查集为基础)
- 当 \(n\) 是偶数时,树边个数是 \(n-1\) 一定是奇数,不可能合法,输出 \(-1\)。
- 我们不管颜色 \(M\) ,把能加入的 \(S\) 色的边加入生成树,记录选入的 \(S\) 色边的条数 \(cnt_1\) 。当 \(cnt_1 < \frac{n-1}{2}\) 时,一定无解。
(因为此时所有的 \(S\) 能加入的都加入了,真实情况只少不多,此时都没到一半,就不可能了。) - 把 \(M\) 色边能加入的加入生成树,并记录 \(cnt_2\) 。如果 \(cnt_1 + cnt_2 < n-1\) 一定无解。
(同样 \(M\) 色的边能加的都加上去了,在所需最少的情况下全部加完都不够,不可能有解。) - 先还原,然后再扫一遍,类似第二步,把 \(S\) 色改成 \(M\) 色即可。(当 \(cnt_2=\frac{n-1}{2}\) 时有解停止。)
思路就是这样,然后直接把 \(S\) 还原即可。
Code
#include <bits/stdc++.h>
#define file(a) freopen(a".in", "r", stdin), freopen(a".out", "w", stdout)
#define quad putchar(' ')
#define Enter putchar('\n')
const int N = 100005;
int n, m, fa[N], tot, cnt1, cnt2, visit[N], ans[N];
struct Node {
int x, y, col;
Node (int _x = 0, int _y = 0, int _col = 0) {x = _x; y = _y; col = _col;}
}node[N];
namespace UFS {
inline void init();
inline int find(int x);
}
using UFS::find;
signed main(void) {
// file("CF141E");
std::cin >> n >> m;
if (n % 2 == 0) {
printf("-1");
return 0;
}
for (int i = 1, x, y; i <= m; i++) {
scanf("%d %d", &x, &y);
char c[4];
scanf("%s", c + 1);
if (c[1] == 'S')
node[++tot] = Node(x, y, 1);
else
node[++tot] = Node(x, y, 2);
}
UFS::init();
for (int i = 1; i <= m; i++) {
int x, y;
if (node[i].col == 2) continue;
x = node[i].x, y = node[i].y;
x = find(x); y = find(y);
if (x == y) continue;
fa[x] = y;
cnt1 ++;
}
if (cnt1 < (n - 1) / 2) {
printf("-1");
return 0;
}
for (int i = 1; i <= m; i++) {
int x, y;
if (node[i].col == 1) continue;
x = node[i].x, y = node[i].y;
x = find(x); y = find(y);
if (x == y) continue;
fa[x] = y; visit[i] = 1;
cnt2 ++;
ans[i] = 1;
}
if (cnt1 + cnt2 < n - 1) {
printf("-1");
return 0;
}
UFS::init();
for (int i = 1; i <= m; i++) {
int x, y;
if (node[i].col == 1) continue;
if (visit[i] == 0) continue;
x = node[i].x, y = node[i].y;
x = find(x); y = find(y);
if (x == y) continue;
fa[x] = y;
}
for (int i = 1; i <= m; i++) {
int x, y;
if (node[i].col == 1) continue;
if (visit[i] == 1) continue;
x = node[i].x, y = node[i].y;
x = find(x); y = find(y);
if (x == y) continue;
fa[x] = y;
cnt2++;
ans[i] = 1;
if (cnt2 == (n - 1) / 2) break;
}
if (cnt2 < (n - 1) / 2) {
printf("-1");
return 0;
}
for (int i = 1; i <= m; i++) {
int x, y;
if (node[i].col == 2) continue;
x = node[i].x, y = node[i].y;
x = find(x); y = find(y);
if (x == y) continue;
fa[x] = y;
ans[i] = 1;
}
printf("%d\n", n - 1);
for (int i = 1; i <= m; i++)
if (ans[i]) printf("%d ", i);
}
namespace UFS {
inline void init() {
for (int i = 1; i <= n; i++)
fa[i] = i;
}
inline int find(int x) {
if (x == fa[x]) return x;
return fa[x] = find(fa[x]);
}
}
CF141E Clearing Up 题解的更多相关文章
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
- 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解
题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...
- 2016ACM青岛区域赛题解
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- poj1399 hoj1037 Direct Visibility 题解 (宽搜)
http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...
- 网络流n题 题解
学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...
- CF100965C题解..
求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...
随机推荐
- 自定义制作SpringBoot启动图案
自定义制作SpringBoot启动图案 一.首先在SpringBoot项目的resources的目录下新建banner.txt文件 二.自定义启动图案 自定义启动图案地址 三.将生成的图形复制粘贴到b ...
- *CTF babyarm内核题目分析
本文从漏洞分析.ARM64架构漏洞利用方式来讨论如何构造提权PoC达到读取root权限的文件.此题是一个ARM64架构的Linux 5.17.2 版本内核提权题目,目的是读取root用户的flag文件 ...
- 比 Navicat 还要好用、功能更强大的工具!
DBeaver 是一个基于 Java 开发,免费开源的通用数据库管理和开发工具,使用非常友好的 ASL 协议.可以通过官方网站或者 Github 进行下载. 由于 DBeaver 基于 Java 开发 ...
- come on! 基于LinkedHashMap实现LRU缓存
/** * @Description 基于LinkedHashMap实现一个基于'LRU最近最少使用'算法的缓存,并且最多存MAX个值 * @Author afei * @date:2021/4/25 ...
- celery介绍、架构、快速使用、包结构,celery执行异步、延迟、定时任务,django中使用celery,定时更新首页轮播图效果实现,数据加入redis缓存的坑及解决
今日内容概要 celery介绍,架构 celery 快速使用 celery包结构 celery执行异步任务 celery执行延迟任务 celery执行定时任务 django中使用celery 定时更新 ...
- stm32F103C8T6通过写寄存器点亮LED灯
因为我写寄存器的操作不太熟练,所以最近腾出时间学习了一下怎么写寄存器,现在把我的经验贴出来,如有不足请指正 我使用的板子是stm32F103C8T6(也就是最常用的板子),现在要通过写GPIO的寄存器 ...
- Hadoop(二)Hdfs基本操作
HDFS HDFS由大量服务器组成存储集群,将数据进行分片与副本,实现高容错. 而分片最小的单位就是块.默认块的大小是64M. HDFS Cli操作 官网https://hadoop.apache.o ...
- dfs深搜
一.01背包dfs //回溯法,01背包 #include<iostream> #include<algorithm> using namespace std; const i ...
- 图解 Git 工作原理
此页图解 git 中的最常用命令.如果你稍微理解git的工作原理,这篇文章能够让你理解的更透彻. 基本用法 上面的四条命令在工作目录.暂存目录(也叫做索引)和仓库之间复制文件. git add fil ...
- 用Docker打包Python运行环境
虽然Docker作为部署环境打包镜像的工具,和我的科研并没有直接的关系.但我觉得在项目中运用Docker来打包环境依赖也可以大大提高工作效率,于是准备专门学习一下Docker. 1. Docker基础 ...