版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40924940/article/details/84330704
这道题 就是求最小割,看着比较简单明了,
那么我们根据 最大流 = 最小割原理,求出最大流 就好了。。。
但是这道题 有一个问题
数据还是很玄学的,需要 dinic 先 bfs 对图进行一下分层,而且还需要一定的剪枝,如果 dinic 的时候有一条路找不到终点,很显然这条路已经没意义了,我们就给这条路堵上。。开始 最后几个点似乎就卡在这里了。。
这道题可以当 dinic 模板 看一看
以下是 AC 代码。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define ll long long int
const int INF = 0x3ffff;
const int maxn = 1e6+5;
ll head[maxn],cnt;
ll h[maxn],q[maxn];
ll st, en, anss;
ll n,m;
struct node
{
ll to,fr;
ll flow;
ll next;
}e[maxn*6];
void add(ll u, ll v, ll w)
{
e[cnt].fr = u, e[cnt].to = v, e[cnt].flow = w;
e[cnt].next = head[u], head[u] = cnt++;
e[cnt].fr = v, e[cnt].to = u, e[cnt].flow = w;
e[cnt].next = head[v], head[v] = cnt++;
}
bool bfs()
{
queue<int>q;
memset(h,0,sizeof(h));
h[st] = 1;
q.push(st);
while(q.size())
{
int now = q.front();
q.pop();
for(int i=head[now]; i!=-1; i=e[i].next)
{
int t = e[i].to;
if(h[t] == 0 && e[i].flow > 0)
{
h[t] = h[now] + 1;
q.push(e[i].to);
}
}
}
return h[en];
}
ll dfs(int u, int flow)
{
if(u == en)
return flow;
ll add = 0;
for(int i=head[u]; i != -1 && add < flow; i=e[i].next)
{
int v = e[i].to;
if(h[v] != h[u] + 1 || !e[i].flow)
continue;
int temp = dfs(v, min(e[i].flow, flow - add));
if(!temp)
{
h[v] = -1;
continue;
}
e[i].flow -= temp;
e[i ^ 1].flow += temp;
add += temp;
}
return add;
}
void dinic()
{
while(bfs())
anss += dfs(st, INF);
}
int gethash(int i, int j)
{
return (i - 1) * m + j;
}
int main()
{
memset(head,-1,sizeof(head));
cin>>n>>m;
st = 1,en = n * m;
anss = 0 ,cnt = 0;
ll tmp;
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j < m; ++j)
{
cin>>tmp;
add(gethash(i, j), gethash(i, j + 1), tmp);
}
}
for(int i = 1; i < n; ++i)
{
for(int j = 1; j <= m; ++j)
{
cin>>tmp;
add(gethash(i, j), gethash(i + 1, j), tmp);
}
}
for(int i = 1; i < n; ++i)
{
for(int j = 1; j < m; ++j)
{
cin>>tmp;
add(gethash(i, j), gethash(i + 1, j + 1), tmp);
}
}
dinic();
cout<<anss<<endl;
return 0;
}