题面

一眼看就是最小割板子题,建图也很直观,注意每一条边建双向边其实不用建4条边,只要反向边的容量和正边相同就行。然后直接跑最大流板子就行。不过此题拿vector存图会MLE……而拿链前存图就能卡过去……场面一度十分尴尬。

这里发一个vector80分代码,各位改成链前就能AC了……

 #include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<stack>
#include<vector>
#include<cctype>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a) memset(a, 0, sizeof(a))
#define rg register
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-;
const int maxn = 1e6 + ;
inline ll read()
{
ll ans = ;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) {last = ch; ch = getchar();}
while(isdigit(ch))
{
ans = ans * + ch - ''; ch = getchar();
}
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < ) putchar('-'), x = -x;
if(x >= ) write(x / );
putchar(x % + '');
} int n, m; struct Edge
{
int from, to, cap, flow;
};
vector<Edge> edges;
vector<int> G[maxn];
void addedge(int from, int to, int w)
{
edges.push_back((Edge){from, to, w, });
edges.push_back((Edge){to, from, w, });
int sz = edges.size();
G[from].push_back(sz - );
G[to].push_back(sz - );
} int dis[maxn];
bool vis[maxn];
bool bfs()
{
for(rg int i = ; i <= n * m; ++i) vis[i] = ;
dis[] = ; vis[] = ;
queue<int> q; q.push();
while(!q.empty())
{
int now = q.front(); q.pop();
for(rg int i = ; i < (int)G[now].size(); ++i)
{
Edge& e = edges[G[now][i]];
if(!vis[e.to] && e.cap > e.flow)
{
vis[e.to] = ;
dis[e.to] = dis[now] + ;
q.push(e.to);
}
}
}
return vis[n * m];
}
int cur[maxn];
int dfs(const int& now, int a)
{
if(now == n * m || !a) return a;
int flow = , f;
for(int& i = cur[now]; i < (int)G[now].size(); ++i)
{
Edge& e = edges[G[now][i]];
if(dis[e.to] == dis[now] + && (f = dfs(e.to, min(a, e.cap - e.flow))) > )
{
e.flow += f;
edges[G[now][i] ^ ].flow -= f;
flow += f; a -= f;
if(!a) break;
}
}
return flow;
} int maxflow()
{
int flow = ;
while(bfs())
{
for(rg int i = ; i <= n * m; ++i) cur[i] = ;
flow += dfs(, INF);
}
return flow;
} int main()
{
n = read(); m = read();
for(rg int i = ; i <= n; ++i)
for(rg int j = ; j < m; ++j)
{
int x = read(), from = (i - ) * m + j, to = (i - ) * m + j + ;
addedge(from, to, x);
}
for(rg int i = ; i < n; ++i)
for(rg int j = ; j <= m; ++j)
{
int x = read(), from = (i - ) * m + j, to = i * m + j;
addedge(from, to, x);
}
for(rg int i = ; i < n; ++i)
for(rg int j = ; j < m; ++j)
{
int x = read(), from = (i - ) * m + j, to = i * m + j + ;
addedge(from, to, x);
}
write(maxflow()); enter;
return ;
}

然后此题据说也可以用对偶图的知识解决。

05-11 13:14