[Codeforces1250E] The Coronation
[Codeforces1250E] The Coronation
又是一道并查集。。。最近做的并查集咋这么多。。。
思路
首先,维护元素间关系的题想到并查集。
因为这里涉及到“翻转”操作。所以我们把反转过后的点\(i\)设为\(i'\),令\(i'=i+n\)。然后使用拆点并查集来计算。
我们把需要同时满足的条件放入一个并查集。然后对于任意两个串,都有四种情况:
- 两个串无论转不转都不相似,显然无解,直接输出-1即可。
- 两个串无论转不转都相似,因为这两个串之间没有相互牵制的限制,所以不管。
- 两个串相似当且仅当其中一个翻转。那么这时候将\(i,j+n\)合并,将\(j,i+n\)合并。(代表了如果取\(i\) , \(j+n\)必须取,反之亦然)
- 两个串相似当且仅当没有一个翻转,那么这时候将\(i,j\)合并,将\(i+n,j+n\)合并。(理由同上)
这样我们就维护了并查集之间的关系。而题目求的就是在满足上述条件情况下,把所有字母代表的点都取到,形如\(i'\)的字母取的最少。我们可以给并查集加权来维护这个东西。
又因为对于\(i\)处于的集合,这个集合和\(i'\)所在的集合的唯一区别是所有字母取反(\(i\)变成\(i'\),\(i'\)变成\(i\))。
所以对于这两个集合,无论取哪个,能取到的字母都是一样的。而同种字母\(i\)和\(i'\)只能取一个。所以取哪个集合效果等价,那我们就贪心的取权值最小的那个集合。
具体看代码实现吧。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
int map[55][55],size[105],n,m,k,fa[105];
bool visit[105];
char s[55];//i=keep i'=i+n=reverse
vector<int>ans;
int check(int u,int v) {
int flag=0;int m1=0,m2=0;
for(int i=1;i<=m;i++){if(map[u][i]^map[v][i])flag++;}
if(flag<=k){m1=1;}
flag=0;
for(int i=1,j=m;i<=m;i++,j--){if(map[u][i]^map[v][j])flag++;}
if(flag<=k){m2=1;}
if(m1&&m2)return 0;
else if(m1&&!m2)return 2;
else if(!m1&&m2)return 1;
else return -1;
}
int get(int x){return (fa[x]==x)?x:(fa[x]=get(fa[x]));}
void uni(int x,int y){size[get(y)]+=size[get(x)];fa[get(x)]=get(y);}
void solve() {
ans.clear();
memset(map,0,sizeof(map));
memset(size,0,sizeof(size));
memset(visit,0,sizeof(visit));
scanf("%d%d%d",&n,&m,&k);k=m-k;
for(int i=1;i<=n;i++) {
scanf("%s",s+1);
for(int j=1;j<=m;j++)map[i][j]=(s[j]=='1')?1:0;
}
for(int i=1;i<=2*n;i++)fa[i]=i;
for(int i=n+1;i<=2*n;i++)size[i]=1;
for(int i=1;i<=n;i++) {
for(int j=i+1;j<=n;j++) {
int tmp=check(i,j);
if(tmp==-1){printf("-1\n");return;}
else if(tmp==1){
if(get(i)==get(i+n)||get(j)==get(j+n)){printf("-1\n");return;}
if(get(i)!=get(j+n)){uni(i,j+n);}
if(get(j)!=get(i+n)){uni(j,i+n);}
}
else if(tmp==2){if(get(i)!=get(j))uni(i,j);if(get(i+n)!=get(j+n))uni(i+n,j+n);}
}
}
for(int i=1;i<=n;i++) {
if(get(i)==get(i+n)){printf("-1\n");return;}
else if(visit[get(i)])continue;
else if(visit[get(i+n)]){ans.push_back(i);continue;}
else if(size[get(i)]>size[get(i+n)]){visit[get(i+n)]=1;ans.push_back(i);}
else {visit[get(i)]=1;}
}
printf("%d\n",ans.size());
for(int i=0;i<ans.size();i++)printf("%d ",ans[i]);
printf("\n");
}
int main() {
int t;scanf("%d",&t);
while(t--)solve();
}
Tips
对于这类维护元素间两两关系(改变一个会同时改变其他的),很容易使用拆点并查集维护。需要注意的是每当我们得到一个信息。我们需要把这个信息能得到的所有关系都体现在并查集中。也就是说要把开出来的虚点当作实际点来处理。举个例子,如果上面的第四种情况只合并了\(i,j\)没有合并\(i+n,j+n\)。会得到WA11的好成绩。

[Codeforces1250E] The Coronation的更多相关文章
- Codeforces 1250E The Coronation
解题思路 用2-SAT的思路将题目转化为:已知\(n\)个二元组\(<x,y>\),可以算出有多少属于不同二元组的元素\((a,b)\)存在冲突,要在每个二元组\(<x,y>\ ...
- words
conscious[英][ˈkɒnʃəs][美][ˈkɑnʃəs]consensus[英][kənˈsensəs][美][kənˈsɛnsəs] scious sensuswaterflood; de ...
- 中英文维基百科语料上的Word2Vec实验
最近试了一下Word2Vec, GloVe 以及对应的python版本 gensim word2vec 和 python-glove,就有心在一个更大规模的语料上测试一下,自然而然维基百科的语料进入了 ...
- The Sorrows of Young Werther
The Sorrows of Young Werther J.W. von Goethe Thomas Carlyle and R.D. Boylan Edited by Nathen Haskell ...
- 2019-2020 ICPC, NERC, Southern and Volga Russian Regional Contest
目录 Contest Info Solutions A. Berstagram B. The Feast and the Bus C. Trip to Saint Petersburg E. The ...
- JavaScript数据可视化编程书籍上面的例子(flotr2)
先看demo再看例子 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...
- TAE words all
// vol 1 could do with sth rhinoplasty angst the wee small hours familial Munich gladi ...
- A Child's History of England.12
Dunstan, Abbot of Glastonbury Abbey, was one of the most sagacious of these monks. He was an ingenio ...
- A Child's History of England.47
CHAPTER 13 ENGLAND UNDER RICHARD THE FIRST, CALLED THE LION-HEART In the year of our Lord one thousa ...
随机推荐
- 为什么不允许使用 Java 静态构造函数?
不允许使用 Java 静态构造函数,但是为什么呢?在深入探讨不允许使用静态构造函数的原因之前,让我们看看如果要使 构造函数静态化 会发生什么. Java 静态构造函数 假设我们有一个定义为的类: pu ...
- 搞定Junit单元测试{非专业}
1:测试分类 2:常用测试方法 2.1 断言语句 3: 基本测试 4: 组合测试 5:参数化测试 6:分类测试(Category) 1:测试分类 1. 黑盒测试:不需要写代码,给输入值,看程序是否能 ...
- Springboot 打包自带启动脚本
一直以来,我都是 gradlew build java -jar xxx.jar 来启动springboot项目的.今天突然发现,springboot自动封装了一个bootJar的任务脚本. demo ...
- jieba 分词使用入门
1. 介绍 JIEBA 是目前最好的 Python 中文分词组件,它主要有以下 3 种特性: 支持 3 种分词模式:精确模式.全模式.搜索引擎模式 支持繁体分词 支持自定义词典 import jieb ...
- okhttp浅析
转载自:http://www.ishenping.com/ArtInfo/69561.html 1.okhttp工作的大致流程 1.1.整体流程 (1).当我们通过OkhttpClient创建一个Ca ...
- Z从壹开始前后端分离【 .NET Core2.2/3.0 +Vue2.0 】框架之七 || API项目整体搭建 6.2 轻量级ORM
本文梯子 本文3.0版本文章 前言 零.今天完成的蓝色部分 0.创建实体模型与数据库 1.实体模型 2.创建数据库 一.在 IRepository 层设计接口 二.在 Repository 层实现相应 ...
- python基础(22):模块、包
1. 模块 1.1 什么是模块 别人写好的函数.变量.方法放在一个文件里 (这个文件可以被我们直接使用)这个文件就是个模块 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模 ...
- 2019 Python100道 面试 题,你会几道?
0 遇到过得反爬虫策略以及解决方法? 1.通过headers反爬虫 2.基于用户行为的发爬虫:(同一IP短时间内访问的频率) 3.动态网页反爬虫(通过ajax请求数据,或者通过JavaScript生成 ...
- 装上这 10 个插件,你就是这条 Gai 最靓的仔!
直奔主题,给大家推荐 10 个好用的插件. 1.「Adblock Plus」 世界排名第一的免费广告拦截程序 相信大家都有这样的体验,进某个论坛.新闻或者购物网站,广告满天飞,关掉之后还时不时弹出 ...
- 跳转常规 -- 为什么不要使用404、500等http状态码作为业务代码响应
不要使用HTTP状态码作为业务代码响应 HTTP状态码 是指浏览器访问网址,成功或异常时浏览器或服务器告知用户的代码数字,它指的是网络或服务器的状态,有着不同的含义. 参加MDN.Java Api,常 ...