zoukankan      html  css  js  c++  java
  • 【JSOI2009】游戏

    题面

    https://www.lydsy.com/JudgeOnline/problem.php?id=1443

    题解

    二分图博弈问题,找一定在匹配上的点,即求可能割边。

    一定在最大流上的边竟然是可能割边,因为如果一条边一定在最大流上,把他删了最大流肯定会减少,也就是最小割会减少,所以是可能割边。

    这是“最小”和“最大”性质的矛盾之处导致的。

    #include<stack>
    #include<queue>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define ri register int
    #define N 10500
    #define S 0
    #define T (wyr+1)
    using namespace std;
    
    const int dx[]={0,1,0,-1},dy[]={1,0,-1,0};
    int n,m,bh[105][105],wyr;
    char g[105][105];
    
    struct network_flow {
      vector<int> ed[N],to,w;
      int d[N],cur[N];
      int bel[N],dfn[N],low[N],cc,cnt;
      bool ins[N]; stack<int> stk;
      
      void add_edge(int u,int v,int aw) {
        to.push_back(v); w.push_back(aw); ed[u].push_back(to.size()-1);
        to.push_back(u); w.push_back(0);  ed[v].push_back(to.size()-1);
      }
      bool bfs() {
        queue<int> q;
        memset(d,0x3f,sizeof(d));
        d[S]=0; q.push(S);
        while (!q.empty()) {
          int x=q.front(); q.pop();
          for (ri i=0;i<ed[x].size();i++) {
            int e=ed[x][i];
            if (w[e] && d[x]+1<d[to[e]]) {
              d[to[e]]=d[x]+1;
              q.push(to[e]);
            }
          }
        }
        return d[T]<1000000007;
      }
      int dfs(int x,int lim) {
        if (x==T || !lim) return lim;
        int sum=0;
        for (ri &i=cur[x];i<ed[x].size();i++) {
          int e=ed[x][i];
          if (w[e] && d[x]+1==d[to[e]]) {
            int f=dfs(to[e],min(lim,w[e]));
            w[e]-=f; w[1^e]+=f;
            sum+=f; lim-=f;
            if (!lim) return sum;
          }
        }
        return sum;
      }
      int dinic() {
        int ret=0;
        while (bfs()) {
          memset(cur,0,sizeof(cur));
          ret+=dfs(S,n*m+1);
        }
        return ret;
      }
      void tarjan(int x) {
        dfn[x]=low[x]=++cc;
        ins[x]=1; stk.push(x);
        for (ri i=0;i<ed[x].size();i++) {
          int e=ed[x][i];
          if (!w[e]) continue;
          if (dfn[to[e]]) {
            if (ins[to[e]]) low[x]=min(low[x],dfn[to[e]]);
          }
          else {
            tarjan(to[e]);
            low[x]=min(low[x],low[to[e]]);
          }
        }
        if (dfn[x]==low[x]) {
          int t; ++cnt;
          do {
            t=stk.top(); stk.pop(); ins[t]=0;
            bel[t]=cnt;
          }
          while (t!=x);
        }
      }
    } G;
    
    bool check() {
      for (ri i=S;i<=T;i++) if (!G.dfn[i]) G.tarjan(i);
      for (ri i=1;i<=n;i++)
        for (ri j=1;j<=m;j++) if (bh[i][j]) {
          if ((i+j)%2==1) {
            if (G.bel[bh[i][j]]!=G.bel[S] && !G.w[2*bh[i][j]-2]) ; else return 1;
          }
          else {
            if (G.bel[bh[i][j]]!=G.bel[T] && !G.w[2*bh[i][j]-2]) ; else return 1;
          }
        }
      return 0;
    }
    
    int main() {
      scanf("%d %d
    ",&n,&m);
      memset(g,'#',sizeof(g));
      for (ri i=1;i<=n;i++) scanf("%s",g[i]+1);
      wyr=0;
      for (ri i=1;i<=n;i++) 
        for (ri j=1;j<=m;j++) if (g[i][j]=='.') bh[i][j]=++wyr;
          
      for (ri i=1;i<=n;i++)
        for (ri j=1;j<=m;j++) if (bh[i][j]) {
          if ((i+j)%2==1) G.add_edge(S,bh[i][j],1); else G.add_edge(bh[i][j],T,1);
        }
      for (ri i=1;i<=n;i++)
        for (ri j=1;j<=m;j++) if (bh[i][j] && (i+j)%2==1) {
          for (ri k=0;k<4;k++) {
            int nx=i+dx[k],ny=j+dy[k];
            if (bh[nx][ny]) G.add_edge(bh[i][j],bh[nx][ny],1);
          }
        }
      G.dinic();
      puts(check()?"WIN":"LOST");
      for (ri i=1;i<=n;i++) 
        for (ri j=1;j<=m;j++) if (bh[i][j]) {
          if ((i+j)%2==1) {
            if (G.bel[bh[i][j]]!=G.bel[S] && !G.w[2*bh[i][j]-2]) ; else printf("%d %d
    ",i,j);
          }
          else {
            if (G.bel[bh[i][j]]!=G.bel[T] && !G.w[2*bh[i][j]-2]) ; else printf("%d %d
    ",i,j);
          }
        }
      return 0;
    }
  • 相关阅读:
    无监督聚类K-means算法
    Python程序执行顺序
    修改jupyter notebook响应的浏览器
    Vijos1035 贪婪的送礼者 [map的应用]
    POJ 2976 Dropping tests [二分]
    POJ 3111 K Best 最大化平均值 [二分]
    HDU 2899 Strange fuction [二分]
    HDU 2141 can you find it [二分]
    HDU 4004 The Frog's Games [二分]
    HDU 1969 Pie [二分]
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11323871.html
Copyright © 2011-2022 走看看