[Codeforces1250E] The Coronation

The Coronation

又是一道并查集。。。最近做的并查集咋这么多。。。

思路

首先,维护元素间关系的题想到并查集。

因为这里涉及到“翻转”操作。所以我们把反转过后的点\(i\)设为\(i'\),令\(i'=i+n\)。然后使用拆点并查集来计算。

我们把需要同时满足的条件放入一个并查集。然后对于任意两个串,都有四种情况:

  1. 两个串无论转不转都不相似,显然无解,直接输出-1即可。
  2. 两个串无论转不转都相似,因为这两个串之间没有相互牵制的限制,所以不管。
  3. 两个串相似当且仅当其中一个翻转。那么这时候将\(i,j+n\)合并,将\(j,i+n\)合并。(代表了如果取\(i\) , \(j+n\)必须取,反之亦然)
  4. 两个串相似当且仅当没有一个翻转,那么这时候将\(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的更多相关文章

  1. Codeforces 1250E The Coronation

    解题思路 用2-SAT的思路将题目转化为:已知\(n\)个二元组\(<x,y>\),可以算出有多少属于不同二元组的元素\((a,b)\)存在冲突,要在每个二元组\(<x,y>\ ...

  2. words

    conscious[英][ˈkɒnʃəs][美][ˈkɑnʃəs]consensus[英][kənˈsensəs][美][kənˈsɛnsəs] scious sensuswaterflood; de ...

  3. 中英文维基百科语料上的Word2Vec实验

    最近试了一下Word2Vec, GloVe 以及对应的python版本 gensim word2vec 和 python-glove,就有心在一个更大规模的语料上测试一下,自然而然维基百科的语料进入了 ...

  4. The Sorrows of Young Werther

    The Sorrows of Young Werther J.W. von Goethe Thomas Carlyle and R.D. Boylan Edited by Nathen Haskell ...

  5. 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 ...

  6. JavaScript数据可视化编程书籍上面的例子(flotr2)

    先看demo再看例子 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

  7. TAE words all

    // vol 1   could do with sth   rhinoplasty   angst   the wee small hours   familial   Munich   gladi ...

  8. 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 ...

  9. 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 ...

随机推荐

  1. 为什么不允许使用 Java 静态构造函数?

    不允许使用 Java 静态构造函数,但是为什么呢?在深入探讨不允许使用静态构造函数的原因之前,让我们看看如果要使 构造函数静态化 会发生什么. Java 静态构造函数 假设我们有一个定义为的类: pu ...

  2. 搞定Junit单元测试{非专业}

    1:测试分类 2:常用测试方法 2.1 断言语句 3: 基本测试 4: 组合测试 5:参数化测试 6:分类测试(Category) 1:测试分类  1. 黑盒测试:不需要写代码,给输入值,看程序是否能 ...

  3. Springboot 打包自带启动脚本

    一直以来,我都是 gradlew build java -jar xxx.jar 来启动springboot项目的.今天突然发现,springboot自动封装了一个bootJar的任务脚本. demo ...

  4. jieba 分词使用入门

    1. 介绍 JIEBA 是目前最好的 Python 中文分词组件,它主要有以下 3 种特性: 支持 3 种分词模式:精确模式.全模式.搜索引擎模式 支持繁体分词 支持自定义词典 import jieb ...

  5. okhttp浅析

    转载自:http://www.ishenping.com/ArtInfo/69561.html 1.okhttp工作的大致流程 1.1.整体流程 (1).当我们通过OkhttpClient创建一个Ca ...

  6. Z从壹开始前后端分离【 .NET Core2.2/3.0 +Vue2.0 】框架之七 || API项目整体搭建 6.2 轻量级ORM

    本文梯子 本文3.0版本文章 前言 零.今天完成的蓝色部分 0.创建实体模型与数据库 1.实体模型 2.创建数据库 一.在 IRepository 层设计接口 二.在 Repository 层实现相应 ...

  7. python基础(22):模块、包

    1. 模块 1.1 什么是模块 别人写好的函数.变量.方法放在一个文件里 (这个文件可以被我们直接使用)这个文件就是个模块 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模 ...

  8. 2019 Python100道 面试 题,你会几道?

    0 遇到过得反爬虫策略以及解决方法? 1.通过headers反爬虫 2.基于用户行为的发爬虫:(同一IP短时间内访问的频率) 3.动态网页反爬虫(通过ajax请求数据,或者通过JavaScript生成 ...

  9. 装上这 10 个插件,你就是这条 Gai 最靓的仔!

    直奔主题,给大家推荐 10 个好用的插件. 1.「Adblock Plus」 世界排名第一的免费广告拦截程序 ​ 相信大家都有这样的体验,进某个论坛.新闻或者购物网站,广告满天飞,关掉之后还时不时弹出 ...

  10. 跳转常规 -- 为什么不要使用404、500等http状态码作为业务代码响应

    不要使用HTTP状态码作为业务代码响应 HTTP状态码 是指浏览器访问网址,成功或异常时浏览器或服务器告知用户的代码数字,它指的是网络或服务器的状态,有着不同的含义. 参加MDN.Java Api,常 ...