[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. Zotero入门精通

    一.Zotero简介 Zotero作为一款协助科研工作者收集.管理以及引用研究资源的免费软件,如今已被广泛使用.此篇使用说明主要分享引用研究资源功能,其中研究资源可以包括期刊.书籍等各类文献和网页.图 ...

  2. 分析Runtime的属性Property

    一.介绍 在OC中我们可以给任意的一个类以@property的格式声明属性,当然对于这个属性也会采用某一些属性关键字进行修饰,那么属性的真正的面目是啥样子的呢?其实,runtime源码中可以看到,pr ...

  3. JAVA 网络编程 - 实现 群聊 程序

    在实现 这个 程序之前, 我们 需要 了解 一些 关于 Java 网络 编程 的 知识. 基本 的 网络知识: 网络模型 OSI (Open System Interconnection 开放系统互连 ...

  4. PyCharm 2017: Remote debugging using remote interpreter doesn't work

    I set up a remote interpreter and verified that I can run a script using the remote interpreter. Con ...

  5. okhttp浅析

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

  6. NumPy 学习 第二篇:索引和切片

    数组索引是指使用中括号 [] 来定位数据元素,不仅可以定位到单个元素,也可以定位到多个元素.索引基于0,并接受从数组末尾开始索引的负索引. 举个例子,正向索引从0开始,从数组开始向末尾依次加1递增:负 ...

  7. Delphi - 创建SuperDll 持续更新

    Delphi SuperDll 作为一名5年的Delpher,一直认为Delphi是桌面应用的王者,我相信其他的Delpher也这么认为. 但是,慢慢的我发现普通方式的Delphi开发会造成代码的严重 ...

  8. ASP.NET中WebService的创建和部署以及通过反射动态调用WebService

    一.在ASP.NET中创建WebService 首先我们先创建一个ASP.NET Web 应用程序,此处我们以VS2017为例 点击新创建的项目,右键添加新建项,选择Web服务,输入名称后点击添加 这 ...

  9. 适合初学者的Python爬取链家网教程

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: TinaLY PS:如有需要Python学习资料的小伙伴可以加点击下 ...

  10. JS基础语法---函数练习part2---10个综合练习(运用:循环/数组/函数)

    练习1:求2个数中的最大值 function getMax(num1, num2) { return num1 > num2 ? num1 : num2; } console.log(getMa ...