CF1147F Zigzag Game

这题太神仙了,不得不记录一下。

我网络流做不动了,DS做不动了,DP做不动了,特别自闭。于是博弈论之神(就是随手切3500博弈的那种) \(\color{black}{\texttt{F}}\color{red}{\texttt{orever_Pursuit}}\) 建议我去学博弈论。

当时看到这题只有两个标签:博弈,交互。就去做了。看到是和交互库玩游戏,感觉很好玩。发现不会,就问了FP。他也不会。然后看题解,发现根本不是博弈(恼。但是这个知识比较重要,还是记一下。准确来说,这是60多年前的论文题/fad,没做过很难现场搞出来。


题解

可以证明选Bob一定必胜(即选择先放棋子)。

首先,我们可以默认我们拿到的操作符是 I ,并且我们选的是左边的数。如果恰好一个有变化,直接把所有边权取相反数即可。

如果必胜,那么意味着我们选了边 \(<a,b>\) ,对方选了 \(<b,c>\) ,我们一定可以找到 \(<c,d>\) ,满足 \(w_{a,b}>w_{b,c},w_{c,d}>w_{b,c}\) 。

这就是稳定婚姻问题,找到一组可行的匹配即可,直接写就完事了简直生草,国外还有论文题。

更明显一点:如果 \(b\) 认为 \(c\) 比 \(a\) 优,那么 \(c\) 一定不能认为 \(b\) 比 \(d\) 优,否则不稳定。

注意两边点的“更优”定义是不同的。左边的点认为更大的更优,右边的点认为更小的更优。

这题没了。可是蒟蒻不会稳定婚姻问题,于是学习笔记就顺带写了(


稳定婚姻问题学习笔记

男孩女孩太不习惯了 ,我们就用这道题的题面,左边的点匹配右边的点

问题定义

给一张完全二分图(你硬说男生在左女生在右也行),每一对左边的点与右边的点之间都有一个评分 \(w_{i,j}\),要求把点两两匹配,满足:

设点 \(a,c\) 在同一边,点 \(b,d\) 在另一边,当前 \((a,b),(c,d)\) 匹配。那么对于所有这种 \((a,b,c,d)\) 不能存在 \(w_{b,a}<w_{b,c}\) (\(b\) 认为\(c\) 比 \(a\) 优)且 \(w_{c,b}>w_{c,d}\) (\(c\) 认为\(b\) 比 \(d\) 优)的情况。

如果存在,那么显然 \(b,c\) 会组成一对,因为这对于 \(b,c\) 来说都更优,那么他们会各自拒绝自己原来的匹配,就不稳定了。

算法流程

定义数组 \(mch_i\) 表示 \(i\) 的匹配。

  • 每次取出一个左边的没有匹配的点。

    • 如果他当前最优的匹配 \(v\) 没有匹配,那么 \(u\) 匹配 \(v\) 。
    • 如果 \(v\) 有匹配并且认为 \(u\) 比他当前的匹配更优,那么 \(u,v\) 匹配,原来的 \(mch_v\) 匹配取消,即 \(mch_v\) 被 \(v\) 拒绝了。
  • 如果每一个节点都有匹配,那么婚姻稳定,退出。

注意 最优匹配 指的是还没有拒绝 \(u\) 的点中,\(u\) 认为最优的匹配。

正确性证明

可行性

假设算法结束后,有一个左边的点和右边的点没有匹配上(存在没匹配那么左右至少各一个点点匹配)

  • 如果一个右边的点被尝试匹配过了,必然有匹配。
  • 如果左边的点一直没有匹配,那么会尝试匹配右边所有的点。

所以右边必然匹配满,那么就不存在失配的问题。

时间复杂度

可以发现,每一个左边的点至多尝试 \(n\) 次与右边的点匹配,那么上界 \(O(n^2)\)

性质

可以发现主动方可以选择到他可以匹配到的最优的匹配。


\(\mathcal{Code}\) (稳定婚姻部分有详细注释。主函数如果你认真看了上面的讲解应该能写出来)

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define mkp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define sz(v) (int)v.size()
typedef long long LL;
typedef double db;
template<class T>bool ckmax(T&x,T y){return x<y?x=y,1:0;}
template<class T>bool ckmin(T&x,T y){return x>y?x=y,1:0;}
#define rep(i,x,y) for(int i=x,i##end=y;i<=i##end;++i)
#define per(i,x,y) for(int i=x,i##end=y;i>=i##end;--i)
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=0;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f?x:-x;
}
const int N=55;
int n,w[N][N],mch[N<<1],kth[N<<1],rk[N<<1][N<<1],ID;
vector<int>e[N<<1];
bool cmp1(const int&a,const int&b){return w[ID][a-n]>w[ID][b-n];}
bool cmp2(const int&a,const int&b){return w[a][ID-n]<w[b][ID-n];}
void init(){//稳定婚姻问题模板
fill(mch+1,mch+n*2+1,0),fill(kth+1,kth+n*2+1,0);
queue<int>q;
rep(i,1,n){
e[i].resize(n+1),e[i+n].resize(n+1);//每一个点的匹配边大小是 n
rep(j,1,n)e[i][j]=j+n,e[i+n][j]=j;//拉边
ID=i,sort(e[i].begin()+1,e[i].begin()+n+1,cmp1);
ID=i+n,sort(e[i+n].begin()+1,e[i+n].begin()+n+1,cmp2);//两边的点对于“优”的定义不同
rep(j,1,n)rk[i][e[i][j]]=j,rk[i+n][e[i+n][j]]=j;//处理对于 i 这个节点的所有可能的匹配 j 在 i 看来的优秀程度
q.push(i);//没有匹配的点丢进队列
}
while(!q.empty()){
int u=q.front();q.pop();//找到一个没有匹配的点
int v=e[u][++kth[u]];//kth 是 u 当前最优的匹配排名
if(!mch[v])mch[u]=v,mch[v]=u;//v 还没有匹配
else if(rk[v][u]<rk[v][mch[v]]){
if(mch[v]<=n)q.push(mch[v]);//mch[v] 失去匹配了,重新丢进队列找匹配
mch[mch[v]]=0,mch[v]=u,mch[u]=v;//v 认为 u 更优
}else q.push(u);//没匹配上,丢进去接着找
}
}
void Main(){
scanf("%d",&n);
rep(i,1,n)rep(j,1,n)w[i][j]=read();
printf("B\n"),fflush(stdout);
char fyyAK[5];int x;
scanf("%s%d",fyyAK,&x);
if((fyyAK[0]=='I')^(x>n))rep(i,1,n)rep(j,1,n)w[i][j]*=-1;
init();
while("fyy txdy"){//只能膜拜!
printf("%d\n",mch[x]),fflush(stdout);
scanf("%d",&x);if(!~x)break;
}
}
signed main(){for(int T=read();T;--T)Main();}

CF1147F Zigzag Game & 稳定婚姻问题学习笔记的更多相关文章

  1. 算法笔记_138:稳定婚姻问题(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 何为稳定婚姻问题? 有一个男士的集合Y = {m1,m2,m3...,mn}和一个女士的计划X = {n1,n2,n3,...,nn}.每一个男士有 ...

  2. 我的Android进阶之旅------>Android中编解码学习笔记

    编解码学习笔记(一):基本概念 媒体业务是网络的主要业务之间.尤其移动互联网业务的兴起,在运营商和应用开发商中,媒体业务份量极重,其中媒体的编解码服务涉及需求分析.应用开发.释放license收费等等 ...

  3. Hadoop入门学习笔记---part2

    在<Hadoop入门学习笔记---part1>中感觉自己虽然总结的比较详细,但是始终感觉有点凌乱.不够系统化,不够简洁.经过自己的推敲和总结,现在在此处概括性的总结一下,认为在准备搭建ha ...

  4. 《Linux内核设计与实现》课本第五章学习笔记——20135203齐岳

    <Linux内核设计与实现>课本第五章学习笔记 By20135203齐岳 与内核通信 用户空间进程和硬件设备之间通过系统调用来交互,其主要作用有三个. 为用户空间提供了硬件的抽象接口. 保 ...

  5. Android自动化学习笔记:编写MonkeyRunner脚本的几种方式

    ---------------------------------------------------------------------------------------------------- ...

  6. AngularJS 1.2.x 学习笔记(表单校验篇)

    https://my.oschina.net/cokolin/blog/526911 摘要: 本文首发于 blog.csdn.net/vipshop_ebs/article/details/39472 ...

  7. Nodejs学习笔记(二)——Eclipse中运行调试Nodejs

    前篇<Nodejs学习笔记(一)——初识Nodejs>主要介绍了在搭建node环境过程中遇到的小问题以及搭建Eclipse开发Node环境的前提步骤.本篇主要介绍如何在Eclipse中运行 ...

  8. android cocos2d-x for Android安装和学习笔记(请用adt-bundle21.1或以上导入)

    引用:http://weimingtom.iteye.com/blog/1483566 (20121108)注意:这篇文章用cdt编译ndk工程的内容已过时(现在可以用adt-bundle,避免配置繁 ...

  9. 《Linux内核设计与实现》课本第一章&第二章学习笔记

    <Linux内核设计与实现>课本学习笔记 By20135203齐岳 一.Linux内核简介 Unix内核的特点 Unix很简洁,所提供的系统调用都有很明确的设计目的. Unix中一切皆文件 ...

随机推荐

  1. 华为+京东数科(原京东金融)面经--Java后台开发

    华为: 1.笔试中遇到的问题,如何解决的?(Scanner 如何结束循环读取数据,笔者在面试中因没有理解到Scanner类的hasNext()与hasNextLine()是阻塞方法,导致没有正确退出循 ...

  2. 磁盘构造/msdos分区(fdisk)格式化(mkfs)和挂载

    分区不是必要的,分区是与系统盘分开,防止数据丢失. 磁盘使用流程:查看磁盘(fdisk -l)---分区---格式化(创建文件系统)----挂载(自动挂载) 分区表类型:msdos(一般是系统分区)  ...

  3. TypeError: Cannot read property 'Component' of undefined

    继续跟着阮一峰的教程走,下面写到PropTypes的getDefaultProps时,又出现了问题,基于上一个createClass的报错换成了Component写法 错误描述: 解决方法:引入rea ...

  4. CTF-Web-强网杯 2019-随便注

    题目链接 题目链接-supersqli FUZZ测试 fuzz出,order by测出数据库查询列数2列,注释符号#,select|update|delete|drop|insert|where|被过 ...

  5. web安全原理-文件包含漏洞

    前言 起来吃完早饭就开始刷攻防世界的题,一个简单的文件包含题我竟然都做不出来我服了  拿出买的书开始从头学习总结文件包含漏洞! 一.文件包含漏洞 文件包含漏洞 文件包含函数的参数没有经过过滤或者严格的 ...

  6. python-Requests模块的使用

    1. Requests简介 Requests模块是一个用于网络访问的模块,其实类似的模块有很多,比如urllib,urllib2,httplib,httplib2,他们基本都提供相似的功能,那为什么R ...

  7. phpstudy搭建网站只能访问首页,其他路由访问404

    今天博主遇到了一个很奇葩的问题,电脑下载了一个phpstudy搭建网站,框架用的是tp,但是除了输入域名能访问,其他页面都访问不了 经过博主的疯狂问大佬,以及百度,终于解决了这个问题 这次出现问题的原 ...

  8. 万字长文带你掌握Java数组与排序,代码实现原理都帮你搞明白!

    查找元素索引位置 基本查找 根据数组元素找出该元素第一次在数组中出现的索引 public class TestArray1 { public static void main(String[] arg ...

  9. 三 CSS基础入门

    CSS介绍 CSS(Cascading Style Sheet,层叠样式表)定义如何显示HTML元素. 当浏览器读到一个样式表,它就会按照这个样式表来对文档进行格式化(渲染). CSS语法 CSS实例 ...

  10. Java里的数组降序

    Java升序容易,降序不易. 基本类型不能降序,至少要是包装类. 升序使用Arrays.sort() 降序要么使用Collections.reverse,要么实现Comparator接口 import ...