题解: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&&sum;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;
}
posted @ 2024-12-11 20:00  Ryan_Adam  阅读(1)  评论(0编辑  收藏  举报