先举个例子,有N台计算机和K个任务,每个计算机只能执行一个任务,但可以执行多种任务。现在给出N和K,和其关系,求出最多能处理的任务数。

这就是典型的二分图,整张图被分为两半,一半是电脑,一半是任务。
在这里插入图片描述

这是多源点多汇点问题,我们只要加上两个点后,就可以把问题转换为单源单汇点问题。
如图:
在这里插入图片描述
看到这个图片大家肯定特别的熟悉,这不就转换为了我们的最大流问题了,权值只不过都是固定的1而已,其他的都是套模板就行。下面代码是FF,可以把其换位Dicnic,不过这道题FF也过了。

下面是poj3041例题AC代码:http://poj.org/problem?id=3041

#include <iostream>
#include <vector>
#include <cstring>
#include <cstdio> 

using namespace std;

const int MAX_N = 500001;
const int INF = 0x3f3f3f3f; 

struct edge
{
	int to, cap, ves;
};

vector<edge> G[MAX_N];
bool used[MAX_N];
int N, K;

void add_edge(int from, int to, int cost)
{
	struct edge e = {to, cost, G[to].size()};
	
	G[from].push_back(e);
	
	struct edge v = {from, 0, G[from].size() - 1};
	
	G[to].push_back(v);
}

int dfs(int v, int t, int f)
{
	if (v == t)
	{
		return f;
	}
	
	used[v] = true;
	
	for (int i=0; i<G[v].size(); i++)
	{
		edge &e = G[v][i];
		
		if (!used[e.to] && e.cap > 0)
		{
			int d = dfs(e.to, t, min(f, e.cap));
			
			if (d > 0)
			{
				e.cap -= d;
				G[e.to][e.ves].cap += d;
				return d;
			}
		}
	}
	
	return 0;
}

int max_flow(int s, int t)
{
	int flow = 0;
	
	for (;;)
	{
		memset(used, 0, sizeof(used));
		
		int f = dfs(s, t, INF);
		
		if (f == 0) 
		{
			return flow;
		}
		
		flow+=f;
	}
}

void slove()
{
	int s = N+K+1, t = s+1;

	for (int i=1; i<=N; i++)
	{
		add_edge(s, i, 1);
	}
	
	for (int i=1; i<=K; i++)
	{
		add_edge(N+i, t, 1);
	}
	
	for (int i=0; i<K; i++)
	{
		int a, b;
		
		cin >> a >> b;
		
		add_edge(a, N+b, 1);
	} 
		
	printf("%d\n", max_flow(s, t));
}

int main()
{
	scanf("%d %d", &N, &K);
	
	slove();
	
	return 0;
} 
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐