题解:AT_abc193_f [ABC193F] Zebraness
题解:AT_abc193_f [ABC193F] Zebraness
Tag
网络流
Solution
我们要求相邻格子颜色不同的最多个数,可以转化为总边数减去相邻格子颜色相同的最少个数。
我们发现颜色相同这一性质很难建图,所以我们将原图黑白染色,染后将黑色格子的原本颜色反转,这样就保证了原本相邻的颜色相同格子变为了颜色不同格子,接下来就直接求修改后图中相邻格子颜色不同的最少个数。这下就最小割板子了,将所有 W
格子与源点 \(s\) 相连,所有 B
与汇点 \(t\) 相连,边权都为 INF
。再把图中存在相邻关系的边一连,在建好的图中跑 Dinic
即可。
注意处理中的细节,需要把二维上的点转换为一维编号。
Code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
const int INF=0x3f3f3f3f;
int n,m,s,t,k;
struct edge
{
int nxt,to,val;
}e[N];
int ans;
int now[N];
int dis[N],head[N],cnt=1;
void add(int u,int v,int w)
{
// cout<<u<<" "<<v<<" "<<w<<endl;
e[++cnt].to=v;
e[cnt].val=w;
e[cnt].nxt=head[u];
head[u]=cnt;
e[++cnt].to=u;
e[cnt].val=0;
e[cnt].nxt=head[v];
head[v]=cnt;
}
bool bfs()
{
memset(dis,-1,sizeof(dis));
queue<int> q;
q.push(s);
dis[s]=0;
now[s]=head[s];
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(e[i].val>0&&dis[v]==-1)
{
q.push(v);
dis[v]=dis[u]+1;
now[v]=head[v];
if(v==t)return 1;
}
}
}
return 0;
}
int dfs(int x,int sum)
{
if(x==t)return sum;
int k,res=0;
for(int i=now[x];i&∑i=e[i].nxt)
{
now[x]=i;
int v=e[i].to;
if(e[i].val>0&&dis[v]==dis[x]+1)
{
k=dfs(v,min(sum,e[i].val));
if(k==0)dis[v]=-1;
e[i].val-=k;
e[i^1].val+=k;
sum-=k;
res+=k;
}
}
return res;
}
void Dinic()
{
while(bfs())
ans+=dfs(s,INF);
return ;
}
char mp[105][105];
int id(int i,int j){return (i-1)*n+j;}
int dd[15][15]={{1,0},{-1,0},{0,1},{0,-1}};
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++)
cin>>mp[i]+1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if((i+j)&1)
{
if(mp[i][j]=='W')mp[i][j]='B';
else if(mp[i][j]=='B')mp[i][j]='W';
}
}
}
s=0,t=n*n+1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
// cout<<"*"<<i<<" "<<j<<" "<<id(i,j)<<endl;
if(mp[i][j]=='B')add(s,id(i,j),INF);
if(mp[i][j]=='W')add(id(i,j),t,INF);
for(int k=0;k<4;k++)
{
if(i+dd[k][0]>=1&&i+dd[k][0]<=n&&j+dd[k][1]>=1&&j+dd[k][1]<=n)
add(id(i,j),id(i+dd[k][0],j+dd[k][1]),1);
}
}
}
Dinic();
// cout << ans << endl;
cout<<2*n*(n-1)-ans<<endl;
return 0;
}