配对问题及最大费用最大流的一般解法。

 

 

最大费用最大流就是把费用搞成负的后再再求最小值,这时反向弧就变成了正的。谨记,切切。

谨记:负环指的是这个环上的费用(路径)权值和为负,现在,一旦是最小费用最大流,应给就是DAG

而最大流的图有可能有环。

那么配对的最小最大以及配对个数统计大多都可以转换成最大流以及最小费用最大流来求解,谨记;

现在是一道题

任务安排

时间限制:5.0s 空间限制:64.0MB

给定N(<=300)个人和N台机器,以及每个人操作某台机器的收益。请计算所有人都工作的情况下,最大的收益和。
输入:
第一行两个数分别表示人和机器的数量(两数相等)
接下来若干行,每行三个数,a,b,c表示a 操作机器b的收益为c.
输出:
两个数。(第一个数表示参加工作的人数(此数为N),第二个数表示最大收益和。)
样例:
输入:
3 3
1 2 10
1 1 9
1 3 3
2 1 10
2 2 9
2 3 3
3 1 8
3 2 9
3 3 8
输出:
3 28

这道题就是典型的配对问题,用人去配对机器。

如果用最小费用最大流来求解,那么重点在建模

一般都是这样,(*^▽^*)。

然后把费用变成负数就是了,附上代码。

 

#include<cstdio>
#include<deque>
#include<cstring>
#define N 100000+10
#define M 100000+10
#define P 300+10
#define inf 1e9
#define ll long long
using namespace std;
int arnum=1,head[N];
struct arc{int next,to,cost,cap;}ar[M];
void add(int from,int to,int cap,int cost){
	ar[++arnum].next=head[from];
	ar[arnum].to=to;
	ar[arnum].cap=cap;
	ar[arnum].cost=cost;
	head[from]=arnum;	
}
void insert(int from,int to,int cap,int cost){add(from,to,cap,cost);add(to,from,0,-cost);}
int book[N],way[M],dis[N],pre[M];
int x[N],y[N];
deque<int>Q;
ll Minflow,Mincost;
int st,en=N-1;
bool SPFA(int n)
{
	memset(book,0,sizeof(book));
 	memset(way,0,sizeof(way));
 	memset(pre,0,sizeof(pre));
	for(int i=1;i<=n;i++)dis[i]=dis[i+P]=inf;
	dis[st]=dis[en]=inf;
	Q.clear();
	dis[st]=0,book[st]=1;
	Q.push_back(st);
	for(;!Q.empty();)
	{
		int u=Q.front();
		Q.pop_front();
		book[u]=0;
		for(int i=head[u];i;i=ar[i].next)
		{
			int v=ar[i].to;
			int cap=ar[i].cap;
			if(cap>0&&dis[v]>dis[u]+ar[i].cost)
			{
				dis[v]=dis[u]+ar[i].cost;
				way[v]=u;
				pre[v]=i;
				if(!book[v])
                 {
                      book[v]=1; 
                      if(Q.empty()||dis[v]>dis[Q.front()])Q.push_back(v);
                         else Q.push_front(v);
                 }
			}
		}
	}
	if(dis[3000]==inf)return false;
	int minn=inf;
	for(int u=en;u!=st;u=way[u])
		minn=min(minn,ar[pre[u]].cap);
	Minflow+=minn;
	Mincost+=minn*dis[en];
	for(int u=en;u!=st;u=way[u])
	{
		ar[pre[u]].cap-=minn;
		ar[pre[u]^1].cap+=minn;
	}
	return true;
}
int main()
{
	int n;
	scanf("%d%d",&n,&n);
	int a,b,c;
	for(;scanf("%d%d%d",&a,&b,&c)==3;)
		insert(a,b+P,1,-c);
	st=0,en=3000;
	for(int i=1;i<=n;i++)
	{
		insert(st,i,1,0);
		insert(i+P,en,1,0);
	}
	for(;SPFA(n););
	printf("%lld %lld\n",Minflow,-Mincost);
	return 0;
}

  

posted @ 2017-10-07 09:51  star_eternal  阅读(1051)  评论(0编辑  收藏  举报