zoukankan      html  css  js  c++  java
  • [bzoj2437]兔兔与蛋蛋

    移动可以理解为空白格的移动,问题等价于双方在一张无向图(相邻不同色点连边,起点视为黑色)移动,不能经过重复的点,无法移动者为负
    由于这张图是二分图,因此有结论,先手必胜当且仅当起点一定在任意一组最大匹配中
    证明:
    必要性,即先手必胜=>一定在匹配中,其等价于不在匹配中=>后手必胜,考虑一组最大匹配,容易发现先手所走到的点一定在最大匹配中(否则匹配可以增大),而后手的策略就是一直走到那个点的匹配上,一定必胜
    充分性,即一定在匹配中=>先手必胜,那么当去掉起点后的最大匹配中,一定存在某一个点使得其可以不在剩下点的最大匹配中,即这个点后手必胜,那么先手走到这个点即可
    具体实现就是说先将其他节点的最大匹配求出,然后再加入这个节点判断能否增大,每一步都只需要重新判断新的空格即可
    (其实这个东西就是说让答案+1即存在一条增广路,而增广路一定是奇数条边,所以差不多就是这样了)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 2005
     4 struct ji{
     5     int nex,to;
     6 }edge[N<<3];
     7 int E,n,m,k,x,y,dx[4]={-1,0,0,1},dy[4]={0,-1,1,0},a[N],vis[N],ans[N],mat[N],head[N];
     8 char s[105][105];
     9 int id(int x,int y){
    10     return x*m+y+1;
    11 }
    12 void add(int x,int y){
    13     edge[E].nex=head[x];
    14     edge[E].to=y;
    15     head[x]=E++;
    16     if (E&1)add(y,x);
    17 }
    18 int dfs(int k){
    19     if ((k<0)||(vis[k]))return 0;
    20     vis[k]=1;
    21     for(int i=head[k];i!=-1;i=edge[i].nex){
    22         int v=edge[i].to;
    23         if ((!mat[v])||(dfs(mat[v]))){
    24             mat[v]=k;
    25             mat[k]=v;
    26             return 1;
    27         }
    28     }
    29     return 0;
    30 }
    31 int main(){
    32     scanf("%d%d",&n,&m);
    33     for(int i=0;i<n;i++)scanf("%s",s[i]);
    34     memset(head,-1,sizeof(head));
    35     for(int i=0;i<n;i++)
    36         for(int j=0;j<m;j++)
    37             if (s[i][j]!='O')
    38                 for(int k=0;k<4;k++){
    39                     x=i+dx[k];
    40                     y=j+dy[k];
    41                     if ((x>=0)&&(y>=0)&&(x<n)&&(y<m)&&(s[x][y]=='O'))add(id(i,j),id(x,y));
    42                 }
    43     for(int i=0;i<n;i++)
    44         for(int j=0;j<m;j++){
    45             if (s[i][j]=='.'){
    46                 x=i+1;
    47                 y=j+1;
    48             }
    49             if (s[i][j]!='O'){
    50                 memset(vis,0,sizeof(vis));
    51                 dfs(id(i,j));
    52             }
    53         }
    54     scanf("%d",&k);
    55     for(int i=0;i<(k<<1);i++){
    56         if (i)scanf("%d%d",&x,&y);
    57         int z=mat[id(--x,--y)];
    58         mat[id(x,y)]=-1;
    59         if (z>0){
    60             mat[z]=0;
    61             memset(vis,0,sizeof(vis));
    62             a[i]=(!dfs(z));
    63         }
    64         if ((i&1)&&(a[i-1])&&(a[i]))ans[++ans[0]]=i/2+1;
    65     }
    66     for(int i=0;i<=ans[0];i++)printf("%d
    ",ans[i]);
    67 }
    View Code
  • 相关阅读:
    axios、ajax、fetch三者的区别
    React与Vue的相同与不同点
    react-redux
    redux【react】
    react高阶组件
    基于WebGL无插件虚拟场景漫游关键技术(完整版)ThingJS
    基于WebGL的三维交通监控可视化技术应用(实践版) ThingJS
    地下管线监控系统中互联网WebGL三维可视化构建技术 ThingJS
    基于WebGL实现智慧校园的全景漫游技术研究 三维可视化
    基于WebGL的3D可视化告警系统关键技术解析 ThingJS
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11818028.html
Copyright © 2011-2022 走看看