题目描述 Description
假设以最美观的方式布置花店的橱窗,有F束花,V个花瓶,我们用美学值(一个整数)表示每束花放入每个花瓶所产生的美学效果。为了取得最佳的美学效果,必须使花的摆放取得最大的美学值。
输入描述 Input Description
第一行为两个整数F,V(F<=V<=100)
接下来F行每行V个整数,第i行第j个数表示第i束花放入第j个花瓶的美学值。
输出描述 Output Description
一个整数,即最大美学值。
样例输入 Sample Input
2 2
10 0
5 2
样例输出 Sample Output
12
数据范围及提示 Data Size & Hint
二分图带权匹配
dinic写傻了,写了个EK……这个算法好不喜欢啊……
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int SZ=100010;
const int INF=1000000000;
int head[SZ],nxt[SZ],tot=1;
struct edge{
int f,t,d,c;
}l[SZ];
void build(int f,int t,int d,int c)
{
l[++tot].t=t;
l[tot].f=f;
l[tot].d=d;
l[tot].c=c;
nxt[tot]=head[f];
head[f]=tot;
}
int s,e,n;
queue<int> q;
int pre[SZ],f[SZ],dist[SZ];
bool use[SZ];
bool spfa(int &cost,int &flow)
{
for(int i=1;i<=n;i++) dist[i]=-INF;
f[s]=INF;
dist[s]=0;
q.push(s);
use[s]=1;
while(q.size())
{
int f=q.front(); q.pop();
use[f]=0;
for(int i=head[f];i;i=nxt[i])
{
int v=l[i].t;
if(l[i].c && dist[v] < dist[f] + l[i].d)
{
dist[v] = dist[f] + l[i].d;
::f[v] = min(::f[f],l[i].c);
pre[v] = i;
if(!use[v])
{
use[v]=1;
q.push(v);
}
}
}
}
if(dist[e]==-INF) return false;
flow += f[e];
cost += dist[e] * f[e];
for(int i=e;i!=s;i=l[pre[i]].f)
{
l[pre[i]].c -= f[e];
l[pre[i]^1].c += f[e];
}
return true;
}
int EK()
{
int cost=0,flow=0;
while(spfa(cost,flow));
return cost;
}
int main()
{
int aa,bb;
scanf("%d%d",&aa,&bb);
n=aa+bb;
for(int i=1;i<=aa;i++)
{
for(int j=aa+1;j<=n;j++)
{
int x;
scanf("%d",&x);
build(i,j,x,1); build(j,i,-x,0);
}
}
s=++n; e=++n;
for(int i=1;i<=aa;i++) build(s,i,0,1),build(i,s,0,0);
for(int i=aa+1;i<=aa+bb;i++) build(i,e,0,1),build(e,i,0,0);
printf("%d\n",EK());
return 0;
}
/*
3 5
7 23 -5 -24 16
5 21 -4 10 23
-21 5 -4 -20 20
*/