W
e
l
c
o
m
e
: )

题解:CF37E Trial for Chief

题目分析

题意

给一张全白的图,每次可以将一个四联通块染黑或染白,求转化到目标最少染色次数。

分析

考虑倒着想,由目标染回原图。

易得倒着染回去和正着染的最少染色次数相同

所以我们考虑从最后的图入手。


考虑从某一个点 \((i,j)\) 开始染色。

尝试进行建图。

在同样的颜色间转移的代价是 \(0\)

如果颜色不同,就需要至少进行一次染色,所以代价是 \(1\)

建图跑最短路即可。

每次跑完后用距离最大的点更新答案。(因为原图是白色,所以只统计黑点)

并且默认一开始需染一次色,所以 \(dis_s=1\)


发现边权只有 \(0\)\(1\)

可以考虑使用 0-1 BFS 求最短路。(其实用 0-1BFS 求的话可以不用建图)

时间复杂度 \(O((nm)^2)\)

Code

#include<bits/stdc++.h>
using namespace std;
#define maxn 52

string tmp;

int mp[maxn][maxn];

#define pos(i, j) (m*((i)-1)+j)
#define chk(i, j) ((i)&&(j)&&(i<=n)&&(j<=m))

vector<pair<int, int> > e[maxn*maxn];

deque<int> dq;
int dis[maxn*maxn];
int bfs(int x, int n, int m)
{
    memset(dis, 0x3f, sizeof dis);
    dis[x]=1;
    dq.emplace_back(x);
    while(!dq.empty())
    {
        auto u=dq.front();
        dq.pop_front();
        for(auto [v, w]:e[u])
            if(dis[v]>dis[u]+w)
            {
                dis[v]=dis[u]+w;
                if(w) dq.emplace_back(v);
                else dq.emplace_front(v);
            }
    }
    int ans=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(mp[i][j]) ans=max(ans, dis[pos(i, j)]);
    return ans;
    
}

int main()
{
    int n, m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>tmp;
        for(int j=1;j<=m;j++)
            mp[i][j]=(tmp[j-1]=='B');
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            if(chk(i-1, j)) e[pos(i, j)].emplace_back(pos(i-1, j), mp[i][j]!=mp[i-1][j]);
            if(chk(i+1, j)) e[pos(i, j)].emplace_back(pos(i+1, j), mp[i][j]!=mp[i+1][j]);
            if(chk(i, j-1)) e[pos(i, j)].emplace_back(pos(i, j-1), mp[i][j]!=mp[i][j-1]);
            if(chk(i, j+1)) e[pos(i, j)].emplace_back(pos(i, j+1), mp[i][j]!=mp[i][j+1]);
        }
    int ans=numeric_limits<int>::max();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            ans=min(ans, bfs(pos(i, j), n, m));
    cout<<ans;
}
posted @ 2024-08-25 20:57  Jimmy-LEEE  阅读(21)  评论(0)    收藏  举报