G. Columns Swaps

题目大意:

两行nnn列,一次操作可以交换同列两个数,要求最小操作次数使两行都是1−n1-n1−n的排列。

前置知识:

2-sat

思路:

每个数都要出现两次这是必要条件。
如果一个数两次出现在同一行,必须一假一真
如果一个数两次出现在不同行,必须同真同假
可以发现本题是无向边(和第几次出现无关),可以用并查集实现。
编号iii 表示真i+ni+ni+n表示假。
并查集的合并:

         for(int i=1;i<=n;i++){  // li 表示第i次出现的列,hi同理if(h1[i]==h2[i]){  // 同一行work(l1[i],l2[i]+n);work(l2[i],l1[i]+n);}else if(l1[i]!=l2[i]){  // 不同行不同列work(l1[i],l2[i]);work(l1[i]+n,l2[i]+n);}}

所有条件的真假不在同一连通块内就一定有解。
操作次数最小:
并查集在合并时,维护每个连通块内真的个数。(也就是操作数)
当前的连通块如果没有作决策选择真假两个块里最小的即可。

             queue<int> ans;for(int i=1;i<=n;i++){int s1=find(i),s2=find(i+n); // 找块if(vis[s1]==0){  // 还没确定if(_size[s1]<_size[s2]){  // 选真更好vis[s1]=1;vis[s2]=-1;}else{vis[s2]=1;vis[s1]=-1;}}if(vis[s1]==1) ans.push(i); }

注意初始化,二倍空间。

Code:

#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
#include <vector>
#include <string>
#include <iomanip>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
//#include <unordered_map>
#define guo312 std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define ll long long
#define Inf LONG_LONG_MAX
#define inf INT_MAX
#define endl "\n"
#define PI 3.1415926535898
using namespace std;
const int N=4e5+10;
int n;
int a[2][N];
map<int,int> mp;
int h1[N],h2[N],l1[N],l2[N];int flag[N],_size[N],vis[N];
void init(){for(int i=1;i<=n*2;i++){flag[i]=i,_size[i]=1,vis[i]=0;if(i>n) _size[i]=0;}
}int find(int x){if(flag[x]==x){return x;}else{return flag[x]=find(flag[x]);}
}void work(int x,int y){int s1=find(x),s2=find(y);if(s1==s2) return ; _size[s1]+=_size[s2],flag[s2]=s1;
}bool ok1(){for(auto it:mp){if(it.second!=2) return 0;}return 1;
}bool ok2(){for(int i=1;i<=n;i++){int s1=find(i),s2=find(i+n);if(s1==s2) return 0;}return 1;
}int main(){guo312;int t; cin>>t; while(t--){cin>>n; mp.clear(); init();for(int j=0;j<=1;j++){for(int i=1;i<=n;i++){cin>>a[j][i];mp[a[j][i]]++;if(mp[a[j][i]]==1){h1[a[j][i]]=j;l1[a[j][i]]=i;}else{h2[a[j][i]]=j;l2[a[j][i]]=i;}}}if(ok1()){for(int i=1;i<=n;i++){if(h1[i]==h2[i]){work(l1[i],l2[i]+n);work(l2[i],l1[i]+n);}else if(l1[i]!=l2[i]){work(l1[i],l2[i]);work(l1[i]+n,l2[i]+n);}}if(ok2()){queue<int> ans;for(int i=1;i<=n;i++){int s1=find(i),s2=find(i+n);if(vis[s1]==0){//cout<<_size[s1]<<" "<<_size[s2]<<" "<<s1<<" "<<s2<<endl; if(_size[s1]<_size[s2]){vis[s1]=1;vis[s2]=-1;}else{vis[s2]=1;vis[s1]=-1;}}if(vis[s1]==1) ans.push(i); }cout<<ans.size()<<endl;while(!ans.empty()){int s=ans.front(); ans.pop();cout<<s<<" "; }cout<<endl;}else{cout<<"-1"<<endl;}}else{cout<<"-1"<<endl;}}return 0;
}

G. Columns Swaps(并查集)相关推荐

  1. Codeforces Gym 101194G Pandaria (2016 ACM-ICPC EC-Final G题, 并查集 + 线段树合并)

    题目链接  2016 ACM-ICPC EC-Final Problem G 题意  给定一个无向图.每个点有一种颜色. 现在给定$q$个询问,每次询问$x$和$w$,求所有能通过边权值不超过$w$的 ...

  2. P2906 [USACO08OPEN]Cow Neighborhoods G 切比雪夫距离 + 并查集 + set

    传送门 考虑将曼哈顿距离转换成切比雪夫距离,这样问题就变成了max(∣x1−x2∣,∣y1−y2∣)≤dmax(|x_1-x_2|,|y_1-y_2|)\le dmax(∣x1​−x2​∣,∣y1​− ...

  3. hdu 6411 带劲的and和(并查集、位运算)

    带劲的and和 Time Limit: 2000/1000 MS (Java/Others) Memory Limit:65536/65536 K (Java/Others) Problem Desc ...

  4. 暑期集训5:并查集 线段树 练习题G: HDU - 1754

    2018学校暑期集训第五天--并查集 线段树 练习题G  --   HDU - 1754 I Hate It 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少.  这让 ...

  5. G - Ice_cream's world I (并查集)

    点击打开链接 ice_cream's world is a rich country, it has many fertile lands. Today, the queen of ice_cream ...

  6. Portals G【并查集】

    >Link luogu P7528 >Description >解题思路 求使每一条边相连通的最小哞尼值 认真想一想,就会发现初始情况,本来就相连通的边会形成一个个环(一个点只有两条 ...

  7. 并查集 问题 G: 极品飞车XX星有许多城市,城市之间通过一种奇怪的高速公路SARS(Super Air Roam Structure---超级空中漫游结构)进行交流,每条SARS都对行驶在上面的Fl

    转载于https://www.cnblogs.com/liyinggang/p/5474341.html 负责解说 题目描述 XX星有许多城市,城市之间通过一种奇怪的高速公路SARS(Super Ai ...

  8. 【BZOJ1015】【JSOI2008】星球大战 并查集

    题目大意 给你一张\(n\)个点\(m\)条边的无向图,有\(q\)次操作,每次删掉一个点以及和这个点相邻的边,求最开始和每次删完点后的连通块个数. \(q\leq n\leq 400000,m\le ...

  9. 1013 Battle Over Cities(并查集解法)

    关于背景的介绍见1013 Battle Over Cities(图的DFS解法) DFS就是不算特定结点后数连通子图的总数,再减一.我想着那么并查集就是数不算特定节点后,集合元素(根)的个数.但是我弄 ...

最新文章

  1. 卷积神经网络学习笔记与心得(4)池化
  2. java软件测试技能要求_软件测试需要掌握什么技能
  3. OpenCV之imgproc 模块. 图像处理(5)在图像中寻找轮廓 计算物体的凸包 创建包围轮廓的矩形和圆形边界框 为轮廓创建可倾斜的边界框和椭圆 轮廓矩 多边形测试
  4. 调整png的不透明度_悄悄告诉你:11个高质量PNG素材来源,再也不用抠图了~
  5. SQL语句中LEFT JOIN、JOIN、INNER JOIN、RIGHT JOIN的区别?
  6. 数组的初始化与默认值
  7. 【Python科学计算系列】概率论与数理统计
  8. MVVM后台ViewModel添加DataGrid表头
  9. Golang的4种传递引用类型
  10. 知易游戏开发教程cocos2d-x移植版
  11. 薛家德(帮别人名字作诗)
  12. adb for linux的工具包,adb工具包下载_adb工具包官方下载「最新版」-太平洋下载中心...
  13. android方向传感器 指南针,Android 方向传感器的两个应用:指南针和水平仪
  14. SDHC卡写单块和读单块
  15. IE浏览器卡死的问题
  16. 第三方分享QQ QQZONE
  17. 星座查询-python
  18. 模仿国内知名B2C网站,实现的一个分布式B2C商城
  19. 基于ARM9程序状态寄存器CPSR
  20. 2008年将是视频中国年

热门文章

  1. win10开机启动慢如何解决?三种方法帮你解决!
  2. tt服务器系统,TT服务器使用手册.doc
  3. 网络游戏怎么样推广引流,游戏推广怎么做引流
  4. python menu_Python——Menu控件
  5. 视频教程-跟汤老师学Java(第18季):设计模式-Java
  6. Building designing
  7. Linux下安装配置使用python虚拟环境
  8. 从SS7到VOIP sip
  9. 树莓派/linux 功能配置(含网络)不定期更新
  10. [转] 25岁,我习得了自愈近视的魔法