QOJ 1197
qoj 1197. Draw in Straight Lines
[!note]
[!tip]
因为不允许先染 \(0\) 在染 \(1\),所以一定是先染黑色,再染白色。
所以我们着色的过程(最优解)一定遵循以下步骤:
- 染黑色
- 染白色
- 单点染色
[!tip]
对于一个格子,不可能存在它被同一方向的染色染两次。
证明:
根据上面的 观察,我们可以尝试计算答案的组成。
先考虑答案中贡献为 \(C\) 部分,它分两种情况:
- 最后应该是 \(0\),但是操作完后 \(1\)。
- 最后应该是 \(1\),但操作完后是 \(0\)。
当发生这两种情况时,答案要被 \(C\) 贡献。
接下来考虑 \(Ax+B\) 的贡献情形:
按照以往的做题经验,一次贡献为 \(Ax+B\) 的形式,往往可以把 \(A\) 进行贡献延迟计算,和 \(B\) 放在一个标志物上进行计算。那么我们 尝试把 \(B\) 放在染色的端点上进行计算,为了方便,我们将 从上往下和从左往右 的两种染色方式的 \(B\) 贡献 放在最上面和最左面进行计算。
但是这个的正确性需要每个位置 最多只被竖着染一次,横着染一次(即不会同向覆盖),显然这个在这道题目中是成立的(参见关键观察 \(2\))。
接下来考虑 最小割模型,套路地,先设出正常的布尔变量:
- \((i,j)\) 是否被 从上往下的 \(0\) 覆盖过,记为 \((i,j,1)\)。
- \((i,j)\) 是否被 从左往右的 \(0\) 覆盖过,记为 \((i,j,2)\)。
- \((i,j)\) 是否被 从上往下的 \(1\) 覆盖过,记为 \((i,j,3)\)。
- \((i,j)\) 是否被 从左往右的 \(1\) 覆盖过,记为 \((i,j,4)\)。
接下来 验证 二元限制是不是一个限制为 \(true\) 且 另一个限制为 \(false\):
- \((i,j,1) \wedge ¬(i-1,j,1)\) 则有 \(B\) 的 代价。(没反)
- \((i,j,2) \wedge ¬(i,j-1,2)\) 则有 \(B\) 的 代价。(没反)
- \((i,j,3) \wedge ¬(i-1,j,3)\) 则有 \(B\) 的 代价。(没反)
- \((i,j,4) \wedge ¬(i,j-1,4)\) 则有 \(B\) 到 代价。(没反)
- \((i,j)\) 这个格子的最终状态是 \(0\),则 \((i,j,3) \wedge (i,j,4)\) 有 \(\infty\) 的 代价。(反了)
- \((i,j)\) 这个格子的最终状态是 \(1\),则 \((i,j,1) \wedge (i,j,2)\) 有 \(\infty\) 的 代价。(反了)
- \((i,j,2) \wedge (i,j,4)\) 有 \(\infty\) 的 代价。(反了)
- \((i,j,1) \wedge (i,j,3)\) 有 \(\infty\) 的 代价。(反了)
解释:
- 第五、六种情况是因为最后不可能被染成 \(0\)(一个格子最多被染 \(2\) 次)
- 第七、八种情况是因为 关键观察 \(2\),不可能发生这种情况,所以代价为 \(\infty\)。
- \((i,j)\) 这个格子的最终状态是 \(0\),则 \((i,j,3) \wedge ¬(i,j,2)\) 有 \(C\) 的 代价。(没反)
- \((i,j)\) 这个格子的最终状态是 \(0\),则 \((i,j,4) \wedge ¬(i,j,1)\) 有 \(C\) 的 代价。(没反)
- \((i,j)\) 这个格子的最终状态是 \(1\),则 \(¬(i,j,3) \wedge ¬(i,j,4)\) 有 \(C\) 的 代价。(反了)
现在有一些 限制 没有反,而有一些 限制 反了,那么 通过 简单、细致、认真、富有想象力和幻想力的观察,我们发现只要翻转 \(1,4\) 限制即可。
时间复杂度:\(\mathcal O(最大流)\)。
代码:
const int N=55,M=5e5+50,inf=2147483647,mod=998244353;
int cas;
int n,m,A,B,C,S,T,tot,cnt=1;
char s[N][N];
int black_line_yes[N][N],black_row_no[N][N],white_line_no[N][N],white_row_yes[N][N];
int head[M],cur[M],dep[M];
struct edge{
int to,nxt,flow;
}e[M];
void add(int u,int v,int flow)
{
e[++cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt;
e[cnt].flow=flow;
}
bool bfs()
{
for(int i=0;i<=T;i++)dep[i]=0;
queue<int> q;q.push(S);dep[S]=1;
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(!dep[v]&&e[i].flow)
{
dep[v]=dep[u]+1;
q.push(v);
}
}
}
return dep[T];
}
int dfs(int u,int flow)
{
if(u==T||!flow)return flow;
int res=0;
for(int& i=cur[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(dep[v]!=dep[u]+1||!e[i].flow)continue;
int f=dfs(v,min(flow-res,e[i].flow));
if(f)
{
res+=f;
e[i].flow-=f;e[i^1].flow+=f;
}else dep[v]=-1;
if(res==flow)return res;
}
return res;
}
int dinic()
{
int maxflow=0;
while(bfs())
{
for(int i=0;i<=T;i++)cur[i]=head[i];
maxflow+=dfs(S,inf);
}
return maxflow;
}
void solve()
{
cin>>n>>m>>A>>B>>C;
for(int i=1;i<=n;i++)cin>>(s[i]+1);
S=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
black_line_yes[i][j]=++tot;//(i,j,4)
black_row_no[i][j]=++tot;//(i,j,3)
white_line_no[i][j]=++tot;//(i,j,2)
white_row_yes[i][j]=++tot;//(i,j,1)
}
}
T=++tot;
for(int i=1;i<=m;i++)white_row_yes[n+1][i]=T,black_line_yes[n+1][i]=T;
for(int i=1;i<=n;i++)black_line_yes[i][m+1]=T,white_row_yes[i][m+1]=T;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
add(white_row_yes[i][j],T,A);add(T,white_row_yes[i][j],0);
add(black_line_yes[i][j],T,A);add(T,black_line_yes[i][j],0);
add(S,white_line_no[i][j],A);add(white_line_no[i][j],S,0);
add(S,black_row_no[i][j],A);add(black_row_no[i][j],S,0);
add(white_row_yes[i][j],white_row_yes[i+1][j],B);add(white_row_yes[i+1][j],white_row_yes[i][j],0);
add(black_line_yes[i][j],black_line_yes[i][j+1],B);add(black_line_yes[i][j+1],black_line_yes[i][j],0);
add(white_line_no[i][j+1],white_line_no[i][j],B),add(white_line_no[i][j],white_line_no[i][j+1],0);
add(black_row_no[i+1][j],black_row_no[i][j],B),add(black_row_no[i][j],black_row_no[i+1][j],0);
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(s[i][j]=='.')//如果 (i,j) 是白色
{
add(black_line_yes[i][j],white_row_yes[i][j],C);add(white_row_yes[i][j],black_line_yes[i][j],0);
add(white_line_no[i][j],black_row_no[i][j],C);add(black_row_no[i][j],white_line_no[i][j],0);
add(black_line_yes[i][j],black_row_no[i][j],inf);add(black_row_no[i][j],black_line_yes[i][j],0);
}
else
{
add(black_row_no[i][j],black_line_yes[i][j],C);add(black_line_yes[i][j],black_row_no[i][j],0);
add(S,white_line_no[i][j],inf);add(white_line_no[i][j],S,0);
add(white_row_yes[i][j],T,inf);add(T,white_row_yes[i][j],0);
}
}
}
cout<<dinic()<<endl;
}
signed main()
{
cas=1;
while(cas--)solve();
return 0;
}


浙公网安备 33010602011771号