• BZOJ 1433 二分图上的博弈


    首先对网格染色,发现是而二分图。

    那么即在二分图上选一个起点走过的点无法再走,最后无路可走就输了。

    如果起点必在最大匹配中,先手必赢。
    如果起点不一定在最大匹配中(包括不可能在),后手必赢。网上有解释。
    因为写二分图不怎么熟练,所以还是用网络流吧。
    找的就是可行的和不在最大匹配中点。建边要用单向边。
    从源点和汇点开始Dfs。假如从左边开始那么先扫到右边后又扫到左边。那么那个点就是可行点。
      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 #include <algorithm>
      5 using namespace std;
      6 const int Maxn=10010;
      7 const int Inf=0x3f3f3f3f;
      8 int n,m,S,T,g[110][110],Color[Maxn],head[Maxn],Level[Maxn],Q[Maxn],u,v,cnt,cur[Maxn],Ans[Maxn],ans;
      9 bool vis[Maxn];
     10 struct Node{int to,next,w;}edge[1000010];
     11 const int dx[4]={0,0,1,-1};
     12 const int dy[4]={1,-1,0,0};
     13 inline int Id(int x,int y) {return (x-1)*m+y;}
     14 inline bool Check(int u,int v) {return ((u<=n&&u>=1)&&(v<=m&&v>=1));}
     15 inline int Min(int x,int y) {return x>y?y:x;}
     16 inline void ADD(int u,int v,int w)
     17 {edge[cnt].to=v;edge[cnt].next=head[u];edge[cnt].w=w;head[u]=cnt++;}
     18 inline void Add(int u,int v,int w) {ADD(u,v,w);ADD(v,u,0);}
     19 bool Bfs()
     20 {
     21     memset(Level,-1,sizeof(Level));
     22     Level[S]=0; Q[1]=S; int l=1,r=1;
     23     while (l<=r)
     24     {
     25         int u=Q[l++];
     26         for (int i=head[u];i!=-1;i=edge[i].next)
     27             if (Level[edge[i].to]==-1 && edge[i].w>0)
     28             {
     29                 Level[edge[i].to]=Level[u]+1;
     30                 Q[++r]=edge[i].to;
     31             }
     32     }
     33     if (Level[T]==-1) return false;
     34     return true;
     35 }
     36 int Find(int u,int low)
     37 {
     38     if (u==T || low==0) return low;
     39     int cap=0;
     40     for (int i=cur[u];i!=-1;i=edge[i].next)
     41         if (edge[i].w>0 && Level[edge[i].to]==Level[u]+1)
     42         {
     43             int tmp=Find(edge[i].to,Min(low,edge[i].w));
     44             if (tmp==0) continue;
     45             low-=tmp,cap+=tmp;
     46             edge[i].w-=tmp,edge[i^1].w+=tmp;
     47             if (edge[i].w>0) cur[u]=i;
     48         }
     49     if (cap) return cap;
     50     Level[u]=-1;
     51     return 0;
     52 }
     53 void Dfs(int u,int c)
     54 {
     55     vis[u]=true;
     56     if (Color[u]==c && u!=S && u!=T) Ans[++ans]=u;
     57     for (int i=head[u];i!=-1;i=edge[i].next)
     58         if (edge[i].w==c && !vis[edge[i].to]) Dfs(edge[i].to,c);
     59 }
     60  
     61 void Get_Ans()
     62 {
     63     memset(vis,false,sizeof(vis)),Dfs(S,1);
     64     memset(vis,false,sizeof(vis)),Dfs(T,0);
     65 }
     66 int main()
     67 {
     68     // freopen("c.in","r",stdin);
     69     // freopen("c.out","w",stdout);
     70     scanf("%d%d",&n,&m);
     71     for (int i=1;i<=n;i++)
     72         for (int j=1;j<=m;j++)
     73         {
     74             char ch=getchar();
     75             while (ch!='.' && ch!='#') ch=getchar();
     76             if (ch=='.') g[i][j]=1;
     77             if (ch=='#') g[i][j]=0;
     78         }
     79     S=0,T=Id(n,m)+1;
     80     memset(head,-1,sizeof(head));
     81     for (int i=1;i<=n;i++)
     82         for (int j=1;j<=m;j++)
     83             if (g[i][j])
     84             {
     85                 if (!((i+j)&1)) 
     86                 {
     87                     Add(S,Id(i,j),1);
     88                     Color[Id(i,j)]=true;
     89                     for (int k=0;k<4;k++)
     90                     {
     91                         int u=i+dx[k],v=j+dy[k];
     92                         if (!Check(u,v)) continue;
     93                         if (g[u][v]) Add(Id(i,j),Id(u,v),1);
     94                     }
     95                 }
     96                 else Add(Id(i,j),T,1);
     97             }
     98     // for (int i=0;i<cnt;i++) printf("%d ",edge[i].to); puts("");
     99     // for (int i=0;i<cnt;i++) printf("%d ",edge[i].w);puts("");
    100     // for (int i=1;i<cnt;i++) printf("%d ",edge[i].next);puts("");
    101     while (Bfs())
    102     {
    103         for (int i=S;i<=T;i++) cur[i]=head[i];
    104         Find(S,Inf);
    105     }
    106     Get_Ans();
    107     if (!ans) puts("LOSE"); else
    108     {
    109         puts("WIN");
    110         sort(Ans+1,Ans+ans+1);
    111         for (int i=1;i<=ans;i++) printf("%d %d
    ",(Ans[i]-1)/m+1,(Ans[i]-1)%m+1);
    112     }
    113     // if ()
    114     return 0;   
    115 }
    C++
  • 相关阅读:
    Reactor系列(四)subscribe订阅
    Reactor系列(三)创建Flux,Mono(续)
    Reactor系列(二)Flux Mono创建
    Reactor系列(一)基本概念
    Stream系列(十五)File方法使用
    Stream系列(十四)parallet方法使用
    OpenCV二值化、归一化操作
    C# 队列
    linux shell脚本程序路径作为变量
    C++中头文件(.h)和源文件(.cpp)都应该写些什么
  • 原文地址:https://www.cnblogs.com/yyjxx2010xyu/p/5487703.html
Copyright © 2020-2023  润新知