zoukankan      html  css  js  c++  java
  • [ TJOI 2010 ] 打扫房间

    (\)

    Description


    给出一个(N imes M) 的网格,一些格子是污点,求是否能用多个封闭的环路覆盖所有不是污点的格点。

    封闭的环路覆盖的含义是,每条路径都必须是一个环,且每一个格点正好只被一条路径覆盖。图是四联通的。

    • (N,Mle 30)

    (\)

    Solution


    一开始以为是插头,后来发现只能做(50\%)的数据......

    将图黑白染色。注意到一个合法的图一定满足每个格点正好进出各一次。每个黑点只能由周围至多的四个白点进出,白点同理。

    所以理论上应该是每个格点都正好达到,向一个异色格点流一股流,从一个异色个点流入一股流,且两个异色格点不为同一个点。

    将问题转化一下,把白色格点流向黑色格点的流反向。

    这样每个黑色格点正好流出两股流,每个白色格点正好流入两股流,我们再加上源汇,源向黑色点流量为 (2) ,白色点向汇流量为 (2)

    这样就转化为满流的判定问题了。

    (\)

    Code


    #include<cmath>
    #include<queue>
    #include<cstdio>
    #include<cctype>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define N 910
    #define R register
    #define gc getchar
    #define inf 2000000000
    using namespace std;
    
    inline int rd(){
      int x=0; bool f=0; char c=gc();
      while(!isdigit(c)){if(c=='-')f=1;c=gc();}
      while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
      return f?-x:x;
    }
    
    bool mp[N][N];
    int n,m,s,t,g,tot,cnt,sum,hd[N],h[N],dp[N],num[35][35];
    
    struct edge{int to,nxt,w;}e[N*100];
    
    inline void add(int u,int v,int w){
      e[++tot].to=v; e[tot].w=w;
      e[tot].nxt=hd[u]; hd[u]=tot;
    }
    
    queue<int> q;
    
    inline bool bfs(){
      memset(dp,0,sizeof(dp));
      dp[s]=1; q.push(s);
      while(!q.empty()){
        int u=q.front(); q.pop();
        for(R int i=hd[u],v;i;i=e[i].nxt)
          if(e[i].w&&!dp[v=e[i].to]){
            dp[v]=dp[u]+1; q.push(v);
          }
      }
      return dp[t];
    }
    
    int dfs(int u,int flow){
      if(u==t||!flow) return flow;
      R int res=0,tmp;
      for(R int &i=h[u],v;i;i=e[i].nxt)
        if(e[i].w&&(dp[v=e[i].to]==dp[u]+1)){
          tmp=dfs(v,min(e[i].w,flow-res));
          e[i].w-=tmp; e[i^1].w+=tmp; res+=tmp;
          if(res==flow) return flow;
        }
      return res;
    }
    
    inline int dinic(){
      int res=0;
      while(bfs()){
        memcpy(h,hd,sizeof(hd));
        res+=dfs(s,inf);
      }
      return res;
    }
    
    
    inline void work(){
      n=rd(); m=rd();
      cnt=g=s=sum=0;
      t=n*m+1; tot=1;
      memset(hd,0,sizeof(hd));
      char c;
      for(R int i=1;i<=n;++i)
        for(R int j=1;j<=m;++j){
          c=gc(); while(c!='.'&&c!='#') c=gc();
          mp[i][j]=(c!='#');
          num[i][j]=++cnt;
          if(c!='#') ++g;
          if((i+j)&1){
            if(mp[i][j]){add(s,cnt,2);add(cnt,s,0);sum+=2;}
          }
          else if(mp[i][j]){add(cnt,t,2);add(t,cnt,0);}
        }
      if(g&1){puts("NO");return;}
      for(R int i=1;i<=n;++i)
        for(R int j=1;j<=m;++j)
        if(mp[i][j]&&((i+j)&1)){
          if(i!=1&&mp[i-1][j]){add(num[i][j],num[i-1][j],1);add(num[i-1][j],num[i][j],0);}
          if(i!=n&&mp[i+1][j]){add(num[i][j],num[i+1][j],1);add(num[i+1][j],num[i][j],0);}
          if(j!=1&&mp[i][j-1]){add(num[i][j],num[i][j-1],1);add(num[i][j-1],num[i][j],0);}
          if(j!=m&&mp[i][j+1]){add(num[i][j],num[i][j+1],1);add(num[i][j+1],num[i][j],0);}
        }
        int ans=dinic();
        puts((ans==sum)?"YES":"NO");
    }
    
    int main(){
      int t=rd();
      while(t--) work();
      return 0;
    }
    
    
  • 相关阅读:
    2008年10月小记(SQL删除重复记录,生成表结构,字符串特性,statistics io)
    mysql 中 @
    使用单个innodb表,实现锁,防止游戏被刷物品或者其它资源!
    PSL
    8年PHP,懂点内核, 能写PHP扩展,5年网站经历+3年webgame经历,找个兼职
    Php aes算法
    MySQL触发器自动更新memcache
    怎么配置MySQL服务器(Incorrect string value)
    使用 PHP 将 XML 转化为易读的数组!
    使用Valgrind 查找内存泄露
  • 原文地址:https://www.cnblogs.com/SGCollin/p/9770405.html
Copyright © 2011-2022 走看看