题解 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~

浙公网安备 33010602011771号