最小费用最大流问题:
题意:n个学生给m个公寓打分,要求你为这些学生分配公寓,使得分配方案得到的总分最高,同时不能安排学生住他打了负分也就是他不喜欢的公寓。
建立超级源点与每个学生相连,容量为1,费用为0。
同理建立超级汇点与每个公寓相连。
在每个学生以及他打分的公寓建立一条边(当然他打了负分的公寓可以直接忽略了),容量为1,费用为他给的分数。
在mincost里调用spfa并统计流量和当前的总费用。
#include<queue>
#include<stdio.h>
#include<iostream>
using namespace std;
#define N 1100
#define M 110000
#define inf 10000000
struct node{
int u,v,cost,flag,next;
}edge[M];
int pre[M],vis[N],head[N],dis[N];
int n,m,l,e,ans,u,v,c,s,t;
int min(int a,int b)
{
if(a<b) return a;
return b;
}
void add_edge(int u,int v,int f,int c)
{
edge[e].u=u; edge[e].v=v; edge[e].cost=c; edge[e].flag=f; edge[e].next=head[u]; head[u]=e++;
edge[e].u=v; edge[e].v=u; edge[e].cost=-c; edge[e].flag=0; edge[e].next=head[v]; head[v]=e++;
}
bool spfa()
{
memset(pre,-1,sizeof(pre));
memset(vis,0,sizeof(vis));
for(int i=0;i<=t;i++)
dis[i]=-inf;
dis[s]=0;
queue<int>q;
q.push(s);
vis[s]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(edge[i].flag>0&&dis[v]<dis[u]+edge[i].cost)
{
dis[v]=dis[u]+edge[i].cost;
pre[v]=i;
if(!vis[v])
{
q.push(v);
vis[v]=1;
}
}
}
}
if(dis[t]==-inf) return false;
return true;
}
int MinCost()
{
int cnt,sum=0,tot=0;
while(spfa())
{
cnt=inf;
for(int j=pre[t];j!=-1;j=pre[edge[j].u])
{
cnt=min(cnt,edge[j].flag);
}
//cout<<cnt<<"!"<<endl;
for(int j=pre[t];j!=-1;j=pre[edge[j].u])
{
edge[j].flag-=cnt;
edge[j^1].flag+=cnt;
}
sum+=(cnt*dis[t]);
tot+=cnt;
}
return tot==n ? sum:-1;
}
int main()
{
int T=0;
while(scanf("%d%d%d",&n,&m,&l)!=EOF)
{
T++;
ans=0; s=n+m+1; t=n+m+2; e=0;
memset(head,-1,sizeof(head));
for(int i=0;i<l;i++)
{
scanf("%d%d%d",&u,&v,&c);
if(c>=0)
add_edge(u,v+n,1,c);
}
for(int i=0;i<n;i++)
add_edge(s,i,1,0);
for(int i=0;i<m;i++)
add_edge(i+n,t,1,0);
printf("Case %d: %d\n",T,MinCost());
}
return 0;
}
hdu 2426 Interesting Housing Problem
最新推荐文章于 2012-10-10 12:38:04 发布