题解 P7338 【『MdOI R4』Color】

P7338 Color

传送门

思路

对于这道题,有一个显然的贪心策略,但是我太弱了赛时没想到...

这种贪心可以去看别的 dalao 的题解,我这篇题解讲述一种不一样的解题思路。

二分图最大匹配

不会的可以左转模板区 ->Click Here<-.

对于一个要求是红色的点,向周围三个方向不要求为红色的点连边,其中要求为红色的点互不连边,不要求的也互不连边,显然,这是一张二分图。

然后设有 $x$ 个点要求为红色,则如果最大匹配数为 $x$,就代表可行,否则不可行。

对于这道题,利用这种方法可以拓展到 $n\times m$ 的矩阵上。

这里有个细节需要注意,每次匹配不能直接 $memset$,这样会导致被卡常。需要打上时间戳,匹配时改一改即可,具体实现见代码。

$Code:$

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,maxn,p[2][N],head[N<<1],match[N<<1],cnt,ans,tim;
int vis[N<<1];
struct edge{
    int to,next;
}a[N<<2];
namespace IO{
    char ibuf[(1<<20)+1],*iS,*iT;
    #if ONLINE_JUDGE
    #define gh() (iS==iT?iT=(iS=ibuf)+fread(ibuf,1,(1<<20)+1,stdin),(iS==iT?EOF:*iS++):*iS++)
    #else
    #define gh() getchar()
    #endif
    #define reg register
    inline int read(){
        reg char ch=gh();
        reg int x=0;
        while(ch<'0'||ch>'9')   ch=gh();
        while(ch>='0'&&ch<='9') x=x*10+(ch^48),ch=gh();
        return x;
    }
    inline int getaint(){
        reg char ch=gh();
        while(ch<'0'||ch>'1') ch=gh();
        return ch-'0';
    }
}using namespace IO;
inline void add(int u,int v){
    cnt++;
    a[cnt].to=v;
    a[cnt].next=head[u];
    head[u]=cnt;
}
inline bool dfs(int x){
    for(int i=head[x];i;i=a[i].next){
        int t=a[i].to;
        if(vis[t]!=tim){
            vis[t]=tim;
            if(!match[t]||dfs(match[t])){
                match[t]=x;
                return true;
            }
        }
    }
    return false;
}
inline void init(){
    cnt=0;
    ans=0;
}
int main(){
    int t=read();
    while(t--){
        init();
        n=read();
        for(int j=0;j<=1;j++){
            for(int i=1;i<=n;i++){
                head[j*n+i]=match[j*n+i]=0;
                p[j][i]=getaint();
            }
        }
        int cnt=0;
        for(int i=0;i<=1;i++){
            for(int j=1;j<=n;j++){
                if(p[i][j]){
                    if(j!=1&&!p[i][j-1]){
                        add(n*i+j,n*i+j-1);
                    }
                    if(j!=n&&!p[i][j+1]){
                        add(n*i+j,n*i+j+1);
                    }
                    if(!p[!i][j]){
                        add(n*i+j,n*(!i)+j);
                    }
                    cnt++;
                }
            }
        }
        for(int i=1;i<=n+n;i++){
            tim++;
            ans+=dfs(i);
        }
        if(ans==cnt){
            puts("RP");
        }else{
            puts("++");
        }
    }
    return 0;
}
/*
Time:96ms
Memory:7.74MB 
*/

再见了 qwq~

posted @ 2021-02-12 14:58  ffffyc  阅读(13)  评论(0)    收藏  举报  来源