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;
}
posted @ 2018-10-19 22:28  菜狗xzz  阅读(164)  评论(0编辑  收藏  举报