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 & ...
 
随机推荐
- Em 和 Rem 的基本使用
			
1. Em html 结构 <div id="box-1"> <h3>Box One</h3> <p> Lorem ipsum do ...
 - day01-从一个基础的socket服务说起
			
首发地址:day01-从一个基础的socket服务说起 教程说明:C++高性能网络服务保姆级教程 本节目的 实现一个基于socket的echo服务端和客户端 服务端监听流程 第一步:使用socket函 ...
 - redis支持的5种数据类型
			
Redis 支持的数据类型:string(字符串).list(列表).hash(字典).set(集 合),zset(有序集合).以下key均为1,此些命令均可直接在redis-cli.exe中执行 s ...
 - windodws pyusb hub端口对应连接的usb设备
			
源码: 1 #!/usr/bin/python 2 import sys 3 import usb.core 4 # find USB devices 5 dev = usb.core.find(fi ...
 - 【CSAPP】Architecture Lab 实验笔记
			
archlab属于第四章的内容.这章讲了处理器体系结构,就CPU是怎样构成的.看到时候跃跃欲试,以为最后实验是真要去造个CPU,配套资料也是一如既往的豪华,合计四十多页的参考手册,一大包的源码和测试程 ...
 - Django学习——Django settings 源码、模板语法之传值、模板语法之获取值、模板语法之过滤器、模板语法之标签、自定义过滤器、标签、inclusion_tag、模板的导入、模板的继承
			
Django settings 源码 """ 1.django其实有两个配置文件 一个是暴露给用户可以自定义的配置文件 项目根目录下的settings.py 一个是项目默 ...
 - goland设置import规范
			
import 规范 引入了三种类型的包,标准库包,第三方包,程序内部包,建议采用如下方式进行组织你的包: 有顺序的引入包,不同的类型采用空格分离, 第一种标准库 第二是第三方包 第三是项目包. 在项目 ...
 - CesiumJS 2022^ 原理[4] - 最复杂的地球皮肤 影像与地形的渲染与下载过程
			
目录 API 回顾 1. 对象层级关系 1.1. Scene 中特殊的物体 - Globe 1.2. 地球 Globe 与椭球 Ellipsoid 1.3. 瓦片四叉树 - QuadtreePrimi ...
 - 异步编程利器:CompletableFuture
			
一.一个示例回顾Future 一些业务场景我们需要使用多线程异步执行任务,加快任务执行速度. JDK5新增了Future接口,用于描述一个异步计算的结果.虽然 Future 以及相关使用方法提供了异步 ...
 - 溢出属性,定位,z-index,JS
			
溢出属性 1.visible(默认值):使溢出内容展示 2.hidden:隐藏溢出内容且不出现滚动条 3.scroll:隐藏溢出容器的内容,溢出的内容可以通过滚动呈现 4.auto:与scroll没啥 ...