codevs 4252 堕落机房

可以裸最小费用最大流。只要相应人,机连边即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#define maxv 805
#define maxe 200005
using namespace std;
struct edge
{
long long v,f,c,nxt;
}e[maxe];
long long g[maxv],n,m,x,s,t,nume=1;
long long dis[maxv],pree[maxv],prev[maxv],rq;
bool vis[maxv];
void addedge(int u,int v,int f,int c)
{
e[++nume].v=v;
e[nume].nxt=g[u];
e[nume].f=f;
e[nume].c=c;
g[u]=nume;
e[++nume].v=u;
e[nume].nxt=g[v];
e[nume].f=0;
e[nume].c=-c;
g[v]=nume;
}
bool spfa()
{
for (int i=0;i<=n+m+1;i++)
{
dis[i]=1000000007;
pree[i]=0;
prev[i]=0;
vis[i]=false;
}
queue <int> q;
q.push(s);
dis[s]=0;
while (!q.empty())
{
int head=q.front();
q.pop();
vis[head]=false;
for (int i=g[head];i;i=e[i].nxt)
{
int v=e[i].v;
if ((dis[v]>dis[head]+e[i].c) && (e[i].f>0) )
{
dis[v]=dis[head]+e[i].c;
pree[v]=i;
prev[v]=head;
if (!vis[v])
{
q.push(v);
vis[v]=true;
}
}
}
}
if (dis[t]==1000000007) return false;
return true;
}
int dinic()
{
rq=0;
long long u=t,delta=1000000007;
while (u!=0)
{
delta=min(delta,e[pree[u]].f);
u=prev[u];
}
u=t;
while (u!=0)
{
e[pree[u]].f=e[pree[u]].f-delta;
e[pree[u]^1].f=e[pree[u]^1].f+delta;
u=prev[u];
}
rq=dis[t]*delta;
return rq;
}
int main()
{
scanf("%lld%lld",&n,&m);
s=0;t=n+m+1;
for (int i=0;i<=m+n+1;i++)
g[i]=0;
for (int i=1;i<=n;i++)
addedge(s,i,1,0);
for (int i=1;i<=m;i++)
addedge(i+n,t,1,0);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
scanf("%lld",&x);
addedge(i,j+n,1,x);
}
long long min_cost=0;
while (spfa()==true)
min_cost=min_cost+dinic();
printf("%lld",min_cost);
return 0;
}

原文地址:https://www.cnblogs.com/ziliuziliu/p/5095963.html