NC23832 Magic Slab(最小割)
Posted 吃花椒的妙酱
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NC23832 Magic Slab(最小割)相关的知识,希望对你有一定的参考价值。
假设所有奖励都能拿到的值sum(每个格子和另外奖励)
每个格子的建图不难想到如下——要么放弃cij的收益,要么消耗ai和bj的值
关联奖励如何建图呢,我们将它作为点单独处理,然后向行列连四个边就行了
答案就是sum-最小割 ,这是网络流做法
我们再看下,花ai,bj去获得cij的收益,也就是-ai-bj -> cij,这是什么?求有向图最大权闭合子图
建图和这题网络流建图一样,cij左集合,ai,bj右集合,权边取绝对值
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <vector>
#include <queue>
using namespace std;
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define _rep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define pb push_back
#define IOS ios::sync_with_stdio(false),cin.tie(0)
//#define int long long
#define inf 0x3f3f3f3f
#define pii pair<int ,int >
#define fi first
#define se second
typedef long long ll;
const int N=3e3+10;
int n,np,nc,m;
int s,t;
int d[N];
int mp[50][50];
struct ty
{
int t,next,flow;
}edge[2*10010];
int tot=1,head[N];
void add(int x ,int y, int flow)
{
edge[++tot]={y,head[x],flow};
head[x]=tot;
edge[++tot]={x,head[y],0};
head[y]=tot;
}
void ini()
{
tot=1;
mst(head,-1);
}
bool bfs(int t)
{
mst(d,0);
queue <int> q;
q.push(s);
d[s]=1;
while( !q.empty() )
{
int x = q.front();
q.pop();
if( x==t ) return true;
for(int i=head[x] ;i!=-1;i=edge[i].next)
{
int y = edge[i].t;
if( edge[i].flow > 0 && !d[y] )
{
d[y] = d[x] + 1;
q.push(y);
}
}
}
return false;
}
int dfs(int x ,int flow ,int t)
{
if( x==t ) return flow;
int sum=0;
for(int i=head[x] ;i!=-1;i=edge[i].next)
{
int y = edge[i].t;
if( d[y] == d[x] +1 && edge[i].flow>0 )
{
int temp = dfs(y,min(edge[i].flow , flow-sum),t);
edge[i].flow -= temp;
edge[i^1].flow += temp;
sum += temp;
if( sum == flow ) return flow;
}
}
if( !sum ) d[x]=0;
return sum;
}
int get(int x ,int y)
{
return n*2+(x-1)*n+y;
}
signed main()
{
// freopen("data.txt","r",stdin);
ini();
cin>>n>>m;
s=0,t=n*n+2*n+m+1;
int sum=0;
_for(i,1,n) _for(j,1,n)
{
cin>>mp[i][j],sum+=mp[i][j];
add(s,get(i,j),mp[i][j]);
add(get(i,j),i,inf);
add(get(i,j),j+n,inf);
}
_for(i,1,n)
{
int x;cin>>x;
add(i,t,x);
}
_for(i,1,n)
{
int x;cin>>x;
add(i+n,t,x);
}
_for(i,1,m)
{
int a,b,c,d,e;cin>>a>>b>>c>>d>>e;
sum += e;
add(s,n*n+2*n+i,e);
add(n*n+2*n+i,a,inf);
add(n*n+2*n+i,b+n,inf);
add(n*n+2*n+i,c,inf);
add(n*n+2*n+i,d+n,inf);
}
//cij和ai,bj不能共存
//行列和s连边
int ans=0;
while( bfs(t) ) ans+=dfs(s,inf,t);
cout<<sum-ans<<endl;//减去最小割
}
以上是关于NC23832 Magic Slab(最小割)的主要内容,如果未能解决你的问题,请参考以下文章