zoukankan      html  css  js  c++  java
  • P3877 [TJOI2010]打扫房间

    xswl以为是个插头dp,然后发现就是个sb题

    相当于就是个匹配。每个格子度数为2,所以可以匹配2个相邻的点。匹配显然的用网络流。最后check有没有不匹配的点即可。

    #include<bits/stdc++.h>
    #define il inline
    #define vd void
    typedef long long ll;
    il int gi(){
        int x=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')f=-1;
            ch=getchar();
        }
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    int S,T;
    int num[32][32][2];
    char s[32][32];
    const int maxn=2000,maxm=100000;
    int fir[maxn],dis[maxm],nxt[maxm],w[maxm],head[maxn],dep[maxn],id;
    il vd link(int a,int b,int c){
        nxt[++id]=fir[a],fir[a]=id,dis[id]=b,w[id]=c;
        nxt[++id]=fir[b],fir[b]=id,dis[id]=a,w[id]=0;
    }
    il bool BFS(){
        static int que[maxn],hd,tl;
        memset(dep,0,sizeof dep);
        hd=tl=0;que[tl++]=S;dep[S]=1;
        while(hd^tl){
            int x=que[hd++];
            for(int i=fir[x];i;i=nxt[i])
                if(w[i]&&!dep[dis[i]])dep[dis[i]]=dep[x]+1,que[tl++]=dis[i];
        }
        return dep[T];
    }
    il int Dinic(int x,int maxflow){
        if(x==T)return maxflow;
        int ret=0;
        for(int&i=head[x];i;i=nxt[i])
            if(w[i]&&dep[dis[i]]==dep[x]+1){
                int d=Dinic(dis[i],std::min(maxflow-ret,w[i]));
                w[i]-=d,w[i^1]+=d,ret+=d;
                if(ret==maxflow)break;
            }
        return ret;
    }
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("3877.in","r",stdin);
        freopen("3877.out","w",stdout);
    #endif
        int yyb=gi(),n,m,cnt;
        while(yyb--){
            n=gi(),m=gi();
            for(int i=1;i<=n;++i)scanf("%s",s[i]+1);
            cnt=0;memset(fir,0,sizeof fir);id=1;
            S=++cnt,T=++cnt;
            for(int i=1;i<=n;++i)
                for(int j=1;j<=m;++j)
                    if(s[i][j]=='.')num[i][j][0]=++cnt,num[i][j][1]=++cnt,link(S,num[i][j][0],2),link(num[i][j][1],T,2);
            int ans=0;
            for(int i=1;i<=n;++i)
                for(int j=1;j<=m;++j)
                    if(s[i][j]=='.'){
                        ans+=2;
                        if(s[i][j+1]=='.')link(num[i][j][0],num[i][j+1][1],1),link(num[i][j+1][0],num[i][j][1],1);
                        if(s[i+1][j]=='.')link(num[i][j][0],num[i+1][j][1],1),link(num[i+1][j][0],num[i][j][1],1);
                    }
            while(BFS())memcpy(head,fir,sizeof fir),ans-=Dinic(S,1e9);
            puts(ans?"NO":"YES");
        }
        return 0;
    }
    
  • 相关阅读:
    【转】C# 注册表简单操作
    [转]VC++之随父窗口变化调整控件大小/位置
    [转]vc 汉字汉语拼音首字母如何获取
    [转]浅析ActiveX控件的CAB压缩
    [转]VC6.0中使用MFC开发ActiveX及简单验证
    ElasticSearch增加索引字段
    单词缩写
    linux命令
    使用PR插件Twixtor Pro对视频补帧
    Linux创建脚本服务
  • 原文地址:https://www.cnblogs.com/xzz_233/p/9819629.html
Copyright © 2011-2022 走看看