[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 ...
随机推荐
- 【STM32H7教程】第18章 STM32H7的GPIO应用之跑马灯
完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第18章 STM32H7的GPIO应用之跑马灯 本 ...
- js中的NaN,isNaN与Number.isNaN的区别,如何判断一个值严格等于NaN
在JavaScript的数字类型Number中,我们最常使用的大概是整数类型与浮点数类型,但除这两者外,还有个特殊的存在NaN,为什么NaN!==NaN?我们如何判断一个值是否等于NaN呢?这篇文章好 ...
- IT兄弟连 HTML5教程 HTML文件的主体结构
每个页面都是一个独立的HTML文档,每个HTML文档的主体结构又都是相同的,而且在一个文档中这样的主体结构只能声明一次.可以简单的将HTML文档主体结构分为两部分,一部分是定义文档类型,HTML5中声 ...
- MySQL应用之CROSS JOIN用法简介教程
目录 2. cross join用法 @ 本博客翻译自两篇博客的: http://www.mysqltutorial.org/mysql-cross-join/ https://www.w3resou ...
- 关于unittest单元测试框架中常用的几种用例加载方法
unittest模块是Python自带的一个单元测试模块,我们可以用来做单元测试.unittest模块包含了如下几个子模块: 测试用例:TestCase 测试集:TestSuite 加载用例:Test ...
- Apollo的基本概念和集成实战
基本概念 使用场景 是一个分布式的配置中心.适用于微服务: 核心功能 集中管理不同环境,不同集群的配置: 配置修改后可以实时推送到应用端: 具备规范的权限,流程治理特性: 开发技术 服务端使用spri ...
- jsp模板
<%String path = request.getContextPath();String basePath = request.getScheme()+"://"+re ...
- SqlServer ----- 根据查询语句创建视图
我们都知道视图的本质就是查询语句,那么就可以根据查询语句创建视图, 前提 知道视图的组成,已经写好的sql 语句,多表或单表的查询语句,将查询语句变成视图. 所以视图可以由单表,多表或视图加表构成. ...
- Visual Studio 2019 16.1 使用 .NET Core 3.0
一.前言 早在很久之前微软便公布 .NET Core 3.0 将支持开发Winform应用程序等等新特性,现如今 .NET Core 3.0 预览版已经出来第五个预览版了,从 .NET Core 2. ...
- C#中 ??、 ?、 ?: 、?.、?[ ] 问号各组合含义
1. 可空类型修饰符(?) 引用类型可以使用空引用表示一个不存在的值,而值类型通常不能表示为空.例如:string str=null; 是正确的,int i=null; 编译器就会报错.为了使值类型也 ...