CF1592F2-Alice and Recoloring 2-分析、二分图
link:https://codeforces.com/contest/1592/problem/F2
题意:给定一个
现在你可以矩阵实施以下操作:
- 使用一块钱,选定一个包含
的子矩阵,把矩阵中的元素全部反转( W 变 B , B 变 W )。 - 使用三块钱,选定一个包含
的子矩阵,把矩阵中的元素全部反转。 - 使用四块钱,选定一个包含
的子矩阵,把矩阵中的元素全部反转。 - 使用两块钱,选定一个包含
的子矩阵,把矩阵中的元素全部反转。
现在需要你求出把初始矩阵变为目标矩阵最少需要几块钱。
首先四个操作中有一些直接是没有用的:
- 右上角花费4元的操作,可以用2次左上角1元解决
- 左下角花费3元的操作,也可以用2次左上角1元解决
- 那么只剩下左上和右下角的
操作相当于区间(二维的)异或,考虑做一个差分数组 (网格外的一律当做单位元 ),那么操作1相当于单点修改 ,右下角相当于修改四个位置
那么就变成:
- 花费1块钱做单点修改
- 花费2块钱可以修改4个特定的位置
对于这 个位置注意到: - (1)一行至多被操作一次,否则
相当于不变,每次只修改 个位置,可以直接用操作1代替 - (2)一个位置如果要修改,必须
都是 ,否则如果有一个不是 ,操作完了还要花钱把它改回来,花费了 块钱,用操作1也是同样的花费
因此对于所有满足
正常用操作1花费是所有
最后考察右下角:看最大流的奇偶性,如果同奇偶性就不用额外花费,否则答案+1
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define endl '\n' #define fastio ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0) using namespace std; template<class T> struct Dinic{//ind from 0 to n-1 struct Edge{ int to;T cap; Edge(int to,T cap):to(to),cap(cap){} }; int n; vector<Edge> E; vector<vector<int>> G; vector<int> cur,h; Dinic(int n=0){init(n);} void init(int n){ this->n=n; E.clear(); cur.resize(n); h.resize(n); G.assign(n,{}); } void addEdge(int u,int v,T c){ G[u].push_back(E.size());E.emplace_back(v,c); G[v].push_back(E.size());E.emplace_back(u,0); } bool bfs(int s,int t){ h.assign(n,-1); queue<int> que; h[s]=0; que.push(s); while(!que.empty()){ const int u=que.front(); que.pop(); for(auto i:G[u]){ auto [v,c]=E[i]; if(c>0&&h[v]==-1){ h[v]=h[u]+1; if(v==t)return true; que.push(v); } } } return false; } T dfs(int u,int t,T f){ if(u==t)return f; auto r=f; for(int &i=cur[u];i<(int)G[u].size();i++){ const int j=G[u][i]; auto [v,c]=E[j]; if(c>0&&h[v]==h[u]+1){ auto a=dfs(v,t,std::min(r,c)); E[j].cap-=a; E[j^1].cap+=a; r-=a; if(r==0)return f; } } return f-r; } T work(int s,int t){ T ans=0; while(bfs(s,t)){ cur.assign(n,0); ans+=dfs(s,t,std::numeric_limits<T>::max()); } return ans; } vector<bool> minCut(){ vector<bool> c(n); rep(i,0,n-1)c[i]=(h[i]!=-1); return c; } struct scheme{ int u,v; T cap,flow; }; vector<scheme> get(){ vector<scheme> ans; for(int i=0;i<(int)E.size();i+=2) ans.push_back({E[i+1].to,E[i].to,E[i].cap+E[i+1].cap,E[i+1].cap}); return ans; } }; int main(){ fastio; int n,m; cin>>n>>m; auto a=vector<vector<int>>(n+2,vector<int>(m+2)); auto s=vector<vector<int>>(n+2,vector<int>(m+2)); rep(i,1,n){ string s; cin>>s; rep(j,1,m)a[i][j]=(s[j-1]=='B'); } rep(i,1,n)rep(j,1,m)s[i][j]=(a[i][j]^a[i+1][j]^a[i][j+1]^a[i+1][j+1]); //[1,n],[n+1,n+m] int S=n+m+1,T=n+m+2; Dinic<int> flow(T+1); int ans=0; rep(i,1,n)rep(j,1,m)ans+=s[i][j]; rep(i,1,n-1)rep(j,1,m-1)if(s[i][j]&&s[n][j]&&s[i][m])flow.addEdge(i,j+n,1); rep(i,1,n)flow.addEdge(S,i,1); rep(j,1,m)flow.addEdge(j+n,T,1); int f=flow.work(S,T); ans-=s[n][m]; ans=ans-f+((f&1)^s[n][m]); cout<<ans; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律