码迷,mamicode.com
首页 > 其他好文 > 详细

POJ1087-A Plug for UNIX(最大流)

时间:2020-07-16 21:25:17      阅读:58      评论:0      收藏:0      [点我收藏+]

标签:一个   sizeof   种类   scan   using   图片   lap   space   ++i   

题意:买了n个插座,m个电器,k个转换器。\(n(1 <= n <= 100)(1 <= m <= 100)(1 <= k <= 100)\),转换器会把\(s1 s2\)中的s2插座转换成s1插座。

//插座个数
4
A
B
C
D
//插头个数
5
laptop B 
phone C 
pager B 
clock B 
comb X 
//转换器种类
3 
B X 
X A 
X D

技术图片

分析:我们可以用map为每个插座赋值一个id,我们从源点向插座连一条容量为1的边,因为每个插座只能适配一个插头。其次,我们为每个插头也赋值一个id,从适配的插座向插头连边,容量为1。然后插头再向汇点连边。我们的交换器比如\(s1 s2\),表示s2的插座器可以向s1的插座器连边,容量为inf。因为交换器是无限的。

注意:每次赋值都要判断一个类型的插座或者插头是否存在。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>

using namespace std;

const int inf = 1 << 29, N = 2005, M = 2 * N;
int h[N], e[M], ne[M], d[N];
int w[M];

int s, t, idx, maxflow;

void add(int a, int b, int c)
{
	e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
	e[idx] = a, w[idx] = 0, ne[idx] = h[b], h[b] = idx++;
}

//构造分层图
bool bfs()
{
	memset(d, 0, sizeof d);
	queue<int> q;
	q.push(s), d[s] = 1;
	while (q.size())
	{
		int u = q.front();
		q.pop();
		for (int i = h[u]; i != -1; i = ne[i])
		{
			int j = e[i];
			if (w[i] && !d[j])
			{
				q.push(j);
				d[j] = d[u] + 1;
				if (j == t) return true;
			}
		}
	}
	return false;
}

int dinic(int u, int flow)
{
	if (u == t) return flow;
	int rest = flow, k;
	for (int i = h[u]; i != -1 && rest; i = ne[i])
	{
		int j = e[i];
		if (w[i] && d[j] == d[u] + 1)
		{
			k = dinic(j, min(rest, w[i]));
			if (!k) d[j] = 0;
			w[i] -= k;
			w[i ^ 1] += k;
			rest -= k;
		}
	}
	return flow - rest;
}

map<string, int> mp;

int main()
{	
	memset(h, -1, sizeof h);
	s = 0, t = 1000;
	//插座个数
	int n;
	scanf("%d", &n);
	string name, name2;

	int id = 0;
	for (int i = 1; i <= n; ++i)
	{
		cin >> name;
		mp[name] = ++id;
		//源点向插座连边
		add(s, id, 1);
	}
	int m;
	//插头个数
	scanf("%d", &m);

	for (int i = 1; i <= m; ++i)
	{
		//插头名和插头类型
		cin >> name >> name2;
		mp[name] = ++id;
		if (mp.find(name2) == mp.end())
		{
			mp[name2] = ++id;
		}
		//插座向插头连边
		add(mp[name2], mp[name], 1);
		//插头向汇点连边
		add(mp[name], t, 1);
	}

	int k;
	scanf("%d", &k);
	for (int i = 1; i <= k; ++i)
	{
		cin >> name >> name2;
		if (mp.find(name) == mp.end())
			mp[name] = ++id;
		if (mp.find(name2) == mp.end())
			mp[name2] = ++id;
		add(mp[name2], mp[name], inf);
	}

	int flow = 0;
	while (bfs())
	{
		while (flow = dinic(s, inf)) maxflow += flow;
	}

	printf("%d\n", m - maxflow);

	return 0;
}

POJ1087-A Plug for UNIX(最大流)

标签:一个   sizeof   种类   scan   using   图片   lap   space   ++i   

原文地址:https://www.cnblogs.com/pixel-Teee/p/13323862.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!