【算法】博弈论+二分图匹配(最大流)

【题解】方格图黑白染色得到二分图,

二分图博弈:当起点不属于某个最大匹配时,后手必胜。

问题转化为那些点不属于某个最大匹配。

先找到一个最大匹配,非匹配点加入答案。

假设一个匹配点要解放成为非匹配点,则与其匹配的点必须去匹配另一个点。如果另一个点也是匹配点,则其对面又要去找另一个点。

最终得到结论,一个匹配点的解放,必须有一个非匹配点进入最大匹配。

那么从S一侧的非匹配点出发,沿着“非匹配边-匹配边”的路径走,途中经过的S一侧的匹配点都可以被解放出来。

从T一侧的非匹配点出发也做一次,得到答案。

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=,inf=0x3f3f3f3f;
const int dx[]={,-,,,};
const int dy[]={,,,,-};
struct edge{int v,from,flow;}e[maxn*];
int first[maxn],id[][],idx[maxn],idy[maxn],S,T,cnt,tot=,d[maxn],ans[maxn],ansnum,cur[maxn],col[maxn],n,m;
char s[];
bool map[][],vis[maxn];
void insert(int u,int v,int w)
{tot++;e[tot].v=v;e[tot].flow=w;e[tot].from=first[u];first[u]=tot;
tot++;e[tot].v=u;e[tot].flow=;e[tot].from=first[v];first[v]=tot;}
queue<int>q;
bool bfs()
{
memset(d,-,sizeof(d));
q.push(S);d[S]=;
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=first[x];i;i=e[i].from)
if(d[e[i].v]==-&&e[i].flow)
{
d[e[i].v]=d[x]+;
q.push(e[i].v);
}
}
return d[T]!=-;
}
int dinic(int x,int a)
{
if(x==T||a==)return a;
int flow=,f;
for(int& i=cur[x];i;i=e[i].from)
if(d[e[i].v]==d[x]+&&(f=dinic(e[i].v,min(a,e[i].flow))))
{
e[i].flow-=f;
e[i^].flow+=f;
a-=f;
flow+=f;
if(a==)break;
}
return flow;
}
void dfs(int x,int f)
{
vis[x]=;
if(col[x]==f&&x!=S&&x!=T)ans[++ansnum]=x;
for(int i=first[x];i;i=e[i].from)
if(e[i].flow==f&&!vis[e[i].v])dfs(e[i].v,f);
}
int main()
{
scanf("%d%d",&n,&m);
cnt=;
for(int i=;i<=n;i++)
{
scanf("%s",s+);
for(int j=;j<=m;j++)if(s[j]=='.')
{
id[i][j]=++cnt;
idx[cnt]=i;idy[cnt]=j;
map[i][j]=;
}
}
S=;T=++cnt;
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)if(map[i][j])
{
if((i+j)&)
{
insert(S,id[i][j],);
for(int k=;k<=;k++)if(map[i+dx[k]][j+dy[k]])
{
insert(id[i][j],id[i+dx[k]][j+dy[k]],);
}
col[id[i][j]]=;
}
else{insert(id[i][j],T,);col[id[i][j]]=;}
}
}
while(bfs())
{
for(int i=;i<=cnt;i++)cur[i]=first[i];
dinic(S,inf);
}
ansnum=;
memset(vis,,sizeof(vis));
dfs(S,);
memset(vis,,sizeof(vis));
dfs(T,);
if(ansnum)
{
printf("WIN\n");
sort(ans+,ans+ansnum+);
for(int i=;i<=ansnum;i++)printf("%d %d\n",idx[ans[i]],idy[ans[i]]);
}
else printf("LOSE\n");
return ;
}

【BZOJ】1443: [JSOI2009]游戏Game的更多相关文章

  1. BZOJ:1443: [JSOI2009]游戏Game

    原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1443 反正不看题解我是完全想不出系列…… 先把棋盘黑白染色,也就是同一对角线上颜色相同,使 ...

  2. BZOJ.1443.[JSOI2009]游戏Game(二分图博弈 匈牙利)

    题目链接 \(Description\) 一个\(N*M\)的有障碍的棋盘,先手放置棋子后,从后手开始轮流移动棋子,不能走重复的位置,不能移动的输.求在哪些位置放棋子是先手必胜的. \(Solutio ...

  3. BZOJ 1443 [JSOI2009]游戏Game ——博弈论

    好题. 首先看到棋盘,先黑白染色. 然后就是二分图的经典模型. 考虑最特殊的情况,完美匹配,那么先手必胜, 因为无论如何,先手走匹配边,后手无论走哪条边,总有对应的匹配边. 如果在不在最大匹配中出发, ...

  4. BZOJ:[JSOI2009]游戏Game【二分图匹配乱搞】

    题目大意:n*m的棋盘,其中有些区域是禁区,两个人在棋盘上进行博弈,后手选择棋子的初始位置,然后先后手轮流将棋子往上下左右移动,走过的区域不能再走,问能否有一个位置使得后手必胜 Input 输入数据首 ...

  5. BZOJ1443: [JSOI2009]游戏Game

    如果没有不能走的格子的话,和BZOJ2463一样,直接判断是否能二分图匹配 现在有了一些不能走的格子 黑白染色后求出最大匹配 如果是完备匹配,则无论如何后手都能转移到1*2的另一端,故先手必输 否则的 ...

  6. JSOI2009 游戏

    1443: [JSOI2009]游戏Game Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 557  Solved: 251[Submit][Stat ...

  7. BZOJ 1444:[JSOI2009]有趣的游戏

    BZOJ 1444:[JSOI2009]有趣的游戏 题目链接 首先我们建出Trie图,然后高斯消元. 我们设\(f_i\)表示经过第\(i\)个点的期望次数: \[ f_x=\sum i\cdot p ...

  8. [BZOJ 2257][JSOI2009]瓶子和燃料 题解(GCD)

    [BZOJ 2257][JSOI2009]瓶子和燃料 Description jyy就一直想着尽快回地球,可惜他飞船的燃料不够了. 有一天他又去向火星人要燃料,这次火星人答应了,要jyy用飞船上的瓶子 ...

  9. 洛谷 P4571 BZOJ 2257 [JSOI2009]瓶子和燃料

    bzoj题目链接 上面hint那里是选择第2个瓶子和第3个瓶子 Time limit 10000 ms Memory limit 131072 kB OS Linux Source Jsoi2009 ...

随机推荐

  1. Null Object Design Pattern (Python recipe)

    Null Object 个人感觉非常有用.也是在review公司其他同事写代码的时候看到. 当时使用了flask的request全局请求变量g,然后使用了g.x保存了一个东西. 当时在view代码读取 ...

  2. jmeter作用域规则

    创建测试计划时,会创建一个有序的一系列将要被执行的请求列表,这些请求通常被组织在有序的控制器下 一些控制器会影响包含在它下面的请求顺序 ,这些特殊的控制器可以参考这里:the component re ...

  3. 14.5 富文本编辑【JavaScript高级程序设计第三版】

    富文本编辑,又称为WYSIWYG(What You See Is What You Get,所见即所得).在网页中编辑富文本内容,是人们对Web 应用程序最大的期待之一.虽然也没有规范,但在IE 最早 ...

  4. P2209 [USACO13OPEN]燃油经济性Fuel Economy

    题面 sol:(思想):开一个大根堆和一个小根堆,每次计算到下了一个加油站用掉的油时尽量用小根堆中的元素,且同时删去大根堆中的相应位置的元素,当前加油站如果足够便宜,就可以把大根堆中的元素替换掉: ( ...

  5. 关于mysql的压测sysbench

    测试表格:CREATE TABLE `sbtest` ( `id` int(10) unsigned NOT NULL auto_increment, `k` int(10) unsigned NOT ...

  6. CF1073E Segment Sum 解题报告

    CF1073E Segment Sum 题意翻译 给定\(K,L,R\),求\(L~R\)之间最多不包含超过\(K\)个数码的数的和. \(K\le 10,L,R\le 10^{18}\) 数位dp ...

  7. 【ATcoder】Xor Sum 2

    题目大意:给定一个 N 个点的序列,求有多少个区间满足\(\oplus_{i=l}^ra[i]=\sum\limits_{i=l}^ra[i]\). 题解: 小结论:\(a\oplus b=a+b\r ...

  8. 【POJ1179】Polygon 区间DP

    这道题是典型的环形石子归并模型,破环成链后时间复杂度为\(O(n^3)\) 不过,因为题目中所给的数字可能是负数,仅仅记录区间内合并之后的最大值并不满足动态规划的最优子结构性质.因此,还需要额外记录下 ...

  9. 笔记: c开发gui程序 (WM_CREATE, WS_CLIPCHILDREN , SetWindowPos)

    过去两年,用c写的gui程序我一般使用的套路是: 在 winMain()中, 先创建一个主窗口, 紧接着就是在下面创建子窗口(子控件). 可能是因为写这方面的程序较少,所以也没遇到什么大问题,之前就是 ...

  10. SQL: 从一个表随机读取一行或几行记录的问题

    比如ms sql 2000,随机读取了一行记录: SELECT TOP 1 * FROM [tablename] ORDER BY NEWID() 遇到的问题是,如果这个表记录不多,比如几十或几百.几 ...