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

Posted star_eternal

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了配对问题及最大费用最大流的一般解法。相关的知识,希望对你有一定的参考价值。

 

 

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

谨记:负环指的是这个环上的费用(路径)权值和为负,现在,一旦是最小费用最大流,应给就是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;
}

  

以上是关于配对问题及最大费用最大流的一般解法。的主要内容,如果未能解决你的问题,请参考以下文章

网络流24题-飞行员配对方案问题-二分图最大匹配

网络流--最小费用最大流 (理解)

最小费用最大流模板

有关网络流题目

最小费用最大流算法

Luogu P4068 [SDOI2016]数字配对(费用流)