[网络流24题]分配问题

题目:洛谷P4014、codevs1915。

题目大意:
有 \( n \) 件工作要分配给 \( n \) 个人做。第 \( i \) 个人做第 \( j \) 件工作产生的效益为 \( c_{ij} \)。求最大总效益和最小总效益(每人只能生产一个零件)。
解题思路:
二分图带权最大/最小匹配。跑费用流即可。
求最大值则费用取负跑,最小值则直接跑,建两遍图跑即可。

C++ Code:

#include<bits/stdc++.h>
using namespace std;
#define T 300
int n;
struct Graph{
	std::queue<int>q;
	int head[305],cnt,pre_e[305],a[305],d[305];
	bool vis[305];
	struct edge{
		int from,to,cap,cost,nxt;
	}e[40005];
	inline void addedge(const int u,const int v,const int flow,const int cost){
		e[++cnt]=(edge){u,v,flow,cost,head[u]};
		head[u]=cnt;
		e[++cnt]=(edge){v,u,0,-cost,head[v]};
		head[v]=cnt;
	}
	Graph():cnt(1){
		memset(head,-1,sizeof head);
	}
	bool bfs(int& flow,int& cost){
		memset(d,0x3f,sizeof d);
		memset(a,0x3f,sizeof a);
		memset(vis,0,sizeof vis);
		memset(pre_e,0,sizeof pre_e);
		d[0]=0;
		vis[0]=1;
		q.push(0);
		while(!q.empty()){
			int u=q.front();q.pop();
			vis[u]=0;
			for(int i=head[u];~i;i=e[i].nxt)
			if(e[i].cap&&d[e[i].to]>d[u]+e[i].cost){
				d[e[i].to]=d[u]+e[i].cost;
				a[e[i].to]=min(a[u],e[i].cap);
				pre_e[e[i].to]=i;
				if(!vis[e[i].to]){
					vis[e[i].to]=1;
					q.push(e[i].to);
				}
			}
		}
		if(d[T]==0x3f3f3f3f)return 0;
		flow+=a[T];
		cost+=d[T]*a[T];
		for(int i=T;i;i=e[pre_e[i]].from){
			e[pre_e[i]].cap-=a[T];
			e[pre_e[i]^1].cap+=a[T];
		}
		return 1;
	}
	int ek(){
		int flow=0,cost=0;
		while(bfs(flow,cost));
		return cost;
	}
}g1,g2;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin>>n;
	for(int i=1;i<=n;++i)
	for(int j=1;j<=n;++j){
		int p;
		cin>>p;
		g1.addedge(i,n+j,1,p);
		g2.addedge(i,n+j,1,-p);
	}
	for(int i=1;i<=n;++i)
	g1.addedge(0,i,1,0),g2.addedge(0,i,1,0),
	g1.addedge(n+i,T,1,0),g2.addedge(n+i,T,1,0);
	cout<<g1.ek()<<'\n'<<-g2.ek()<<'\n';
	return 0;
}

 

posted @ 2018-06-03 19:23  Mrsrz  阅读(172)  评论(0编辑  收藏  举报