题意分析
一看就是一道网络流的题目,然后上去最大流直接搞。
然后发现超时了,所以学了一波当前弧优化,然后就过了。
然后我觉得还可以再快一点,就IO加速了一下, 发现速度提高了400ms。
嗯,FASTIO还是很强的。
还有这道题是无向图,所以正反边容量都是w,一开始我建成正边w反边0,过不了。原因是有向图和无向图还是不一样的,会影响到增广的情况。
另外因为是平面图,所以可以求出对偶图,然后用最短路来求最小割。
我懒所以就不想学了。
代码总览
#include<bits/stdc++.h>
#define FI(n) FastIO::read(n)
using namespace std;
const int nmax = 1e6+10;
typedef struct{
int to,nxt,w;
}Edge;
Edge e[nmax*6];
int head[nmax], dep[nmax];
int cur[nmax];
int tot = 0;
int n,m;
namespace FastIO {
const int SIZE = 1 << 16;
char buf[SIZE], obuf[SIZE], str[60];
int bi = SIZE, bn = SIZE, opt;
int read(char *s) {
while (bn) {
for (; bi < bn && buf[bi] <= ' '; bi++);
if (bi < bn) break;
bn = fread(buf, 1, SIZE, stdin);
bi = 0;
}
int sn = 0;
while (bn) {
for (; bi < bn && buf[bi] > ' '; bi++) s[sn++] = buf[bi];
if (bi < bn) break;
bn = fread(buf, 1, SIZE, stdin);
bi = 0;
}
s[sn] = 0;
return sn;
}
bool read(int& x) {
int n = read(str), bf;
if (!n) return 0;
int i = 0; if (str[i] == '-') bf = -1, i++; else bf = 1;
for (x = 0; i < n; i++) x = x * 10 + str[i] - '0';
if (bf < 0) x = -x;
return 1;
}
};
void add(int u, int v, int w){
e[tot].to = v;
e[tot].nxt = head[u];
e[tot].w = w;
head[u]=tot++;
}
bool bfs(){
queue<int> q;
memset(dep,0,sizeof dep); dep[1] = 1; q.push(1);
while(!q.empty()){
int u = q.front(); q.pop();
for(int i = head[u]; i!=-1;i = e[i].nxt){
int v = e[i].to;
if(e[i].w > 0 && dep[v] == 0){
dep[v] = dep[u] +1;
q.push(v);
}
}
}
return dep[n*m] != 0;
}
int dfs(int u, int dis){
if(u == n*m || dis == 0) return dis;
for(int & i = cur[u];i!=-1;i=e[i].nxt){
int v = e[i].to, w = e[i].w;
if(dep[v] == dep[u] +1 && w > 0){
int tt = dfs(v,min(dis,w));
if(tt > 0){
e[i].w -= tt;
e[i^1].w += tt;
return tt;
}
}
}
return 0;
}
int Dinic(){
int ans = 0;
while(bfs()){
for(int i = 1;i<=n*m;++i) cur[i] = head[i];
while(int t = dfs(1,0x3f3f3f3f))
ans += t;
}
return ans;
}
int main(){
memset(head,-1,sizeof head);
FI(n);FI(m);
int w;
for(int i = 0;i<n;++i){
for(int j = 1;j<m;++j){
FI(w);
add(i*m+j,i*m+j+1,w);
add(i*m+j+1,i*m+j,w);
}
}
for(int i = 1;i<=n-1;++i){
for(int j = 1;j<=m;++j){
FI(w);
add((i-1)*m+j,i*m+j,w);
add(i*m+j,(i-1)*m+j,w);
}
}
for(int i = 1;i<=n-1;++i){
for(int j = 1;j<=m-1;++j){
FI(w);
add((i-1)*m+j,i*m+j+1,w);
add(i*m+j+1,(i-1)*m+j,w);
}
}
printf("%d\n",Dinic());
return 0;
}