P4003 无限之环 题解
首先这个网格图就说明了一些问题。一般地,网格图主要的解决方法是 dp(尤其是插头 dp)。但是这个题里需要解决的只有相邻两个格子之间的相邻性问题,于是采取网格图另一个常见的思路:二分图染色。于是将这个网格图黑白染色,将一个格子的四壁拆成四个点,相邻的壁之间连边。这样就是一个二分图的模型了。
然后考虑 SB 的旋转操作。考虑这样建模的实质是什么。事实上网络的流量就是水管的指向,于是改变水管的指向就是要改变流量的转移。考虑能否在四壁之间相互转移,注意到除了直线型的都可以表示,然后发现直线不能转移,然后这题就做完了。
代码:
#include <bits/stdc++.h>
#define N 100005
#define M 2000005
#define inf 0x3f3f3f3f
#define pii pair<int, int>
#define mk make_pair
using namespace std;
int n, m;
struct Dinic {
int n, s, t;
struct Node {
int to, nxt, fl, dis;
} e[M];
int head[N], cnt = 1;
void add(int u, int v, int w = 0, int f = 1) {
e[++cnt].to = v;
e[cnt].fl = f;
e[cnt].dis = w;
e[cnt].nxt = head[u];
head[u] = cnt;
e[++cnt].to = u;
e[cnt].fl = 0;
e[cnt].dis = -w;
e[cnt].nxt = head[v];
head[v] = cnt;
}
int dis[N], inr[N];
int pre[N];
bool vis[N];
int SPFA() {
for (int i = 1; i <= n; i++) dis[i] = inf;
queue<int>q;
q.push(s);
dis[s] = 0;
inr[s] = inf;
while (q.size()) {
int x = q.front();
q.pop();
vis[x] = 0;
for (int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if (e[i].fl > 0 && dis[y] > dis[x] + e[i].dis) {
dis[y] = dis[x] + e[i].dis;
pre[y] = i;
inr[y] = min(inr[x], e[i].fl);
if (!vis[y]) {
vis[y] = 1;
q.push(y);
}
}
}
}
return dis[t] < inf;
}
pii MCMF() {
int fl = 0, cost = 0;
while (SPFA()) {
fl += inr[t];
cost += inr[t] * dis[t];
int i;
for (int x = t; x != s; x = e[i ^ 1].to) {
i = pre[x];
e[i].fl -= inr[t];
e[i ^ 1].fl += inr[t];
}
}
return mk(fl, cost);
}
} dc;
int gt(int x, int y) {
return (x - 1) * m + y - 1;
}
int up(int x, int y) {
return (gt(x, y) << 2) | 1;
}
int rg(int x, int y) {
return (gt(x, y) << 2) + 2;
}
int dn(int x, int y) {
return (gt(x, y) << 2) + 3;
}
int lf(int x, int y) {
return (gt(x, y) << 2) + 4;
}
#define add dc.add
#define s dc.s
#define t dc.t
int chk(int x, int y) {
return 1 <= x && x <= n && 1 <= y && y <= m;
}
int sum;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m;
s = ((n * m) << 2) + 1, t = dc.n = s + 1;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
int x;
cin >> x;
sum += __builtin_popcount(x);
int u = up(i, j), d = dn(i, j), l = lf(i, j), r = rg(i, j);
if ((i + j) & 1) {
if (chk(i - 1, j)) add(u, dn(i - 1, j));
if (chk(i + 1, j)) add(d, up(i + 1, j));
if (chk(i, j - 1)) add(l, rg(i, j - 1));
if (chk(i, j + 1)) add(r, lf(i, j + 1));
if (x == 1) {
add(s, u);
add(u, l, 1);
add(u, r, 1);
add(u, d, 2);
}
else if(x == 2) {
add(s, r);
add(r, u, 1);
add(r, d, 1);
add(r, l, 2);
}
else if(x == 4) {
add(s, d);
add(d, l, 1);
add(d, r, 1);
add(d, u, 2);
}
else if(x == 8) {
add(s, l);
add(l, u, 1);
add(l, d, 1);
add(l, r, 2);
}
else if(x == 5) {
add(s, u);
add(s, d);
}
else if(x == 10) {
add(s, l);
add(s, r);
}
else if(x == 3) {
add(s, u);
add(s, r);
add(u, d, 1);
add(r, l, 1);
}
else if(x == 9) {
add(s, u);
add(s, l);
add(u, d, 1);
add(l, r, 1);
}
else if(x == 6) {
add(s, d);
add(s, r);
add(d, u, 1);
add(r, l, 1);
}
else if(x == 12) {
add(s, d);
add(s, l);
add(d, u, 1);
add(l, r, 1);
}
else if(x == 11) {
add(s, u);
add(s, l);
add(s, r);
add(l, d, 1);
add(r, d, 1);
add(u, d, 2);
}
else if(x == 14) {
add(s, d);
add(s, l);
add(s, r);
add(l, u, 1);
add(r, u, 1);
add(d, u, 2);
}
else if(x == 13) {
add(s, l);
add(s, u);
add(s, d);
add(u, r, 1);
add(d, r, 1);
add(l, r, 2);
}
else if(x == 7) {
add(s, r);
add(s, u);
add(s, d);
add(u, l, 1);
add(d, l, 1);
add(r, l, 2);
}
else if(x == 15) {
add(s, u);
add(s, d);
add(s, l);
add(s, r);
}
}
else {
if (x == 1) {
add(u, t);
add(l, u, 1);
add(r, u, 1);
add(d, u, 2);
}
else if(x == 2) {
add(r, t);
add(u, r, 1);
add(d, r, 1);
add(l, r, 2);
}
else if(x == 4) {
add(d, t);
add(l, d, 1);
add(r, d, 1);
add(u, d, 2);
}
else if(x == 8) {
add(l, t);
add(u, l, 1);
add(d, l, 1);
add(r, l, 2);
}
else if(x == 5) {
add(u, t);
add(d, t);
}
else if(x == 10) {
add(l, t);
add(r, t);
}
else if(x == 3) {
add(u, t);
add(r, t);
add(d, u, 1);
add(l, r, 1);
}
else if(x == 9) {
add(u, t);
add(l, t);
add(d, u, 1);
add(r, l, 1);
}
else if(x == 6) {
add(d, t);
add(r, t);
add(u, d, 1);
add(l, r, 1);
}
else if(x == 12) {
add(d, t);
add(l, t);
add(u, d, 1);
add(r, l, 1);
}
else if(x == 11) {
add(u, t);
add(l, t);
add(r, t);
add(d, l, 1);
add(d, r, 1);
add(d, u, 2);
}
else if(x == 14) {
add(d, t);
add(l, t);
add(r, t);
add(u, l, 1);
add(u, r, 1);
add(u, d, 2);
}
else if(x == 13) {
add(l, t);
add(u, t);
add(d, t);
add(r, u, 1);
add(r, d, 1);
add(r, l, 2);
}
else if(x == 7) {
add(r, t);
add(u, t);
add(d, t);
add(l, u, 1);
add(l, d, 1);
add(l, r, 2);
}
else if(x == 15) {
add(u, t);
add(d, t);
add(l, t);
add(r, t);
}
}
}
pii ans = dc.MCMF();
if ((ans.first << 1) != sum) cout << "-1\n";
else cout << ans.second << "\n";
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】