POJ - 2584(二分匹配入门)

Time Limit: 1000MS Memory Limit: 65536KB 64bit IO Format: %lld & %llu

Status

Description

Boudreaux and Thibodeaux are student volunteers for this year's ACM South Central Region's programming contest. One of their duties is to distribute the contest T-shirts to arriving teams. The T-shirts had to be ordered in advance using an educated guess as to how many shirts of each size should be needed. Now it falls to Boudreaux and Thibodeaux to determine if they can hand out T-shirts to all the contestants in a way that makes everyone happy.

Input

Input to this problem will consist of a (non-empty) series of up to 100 data sets. Each data set will be formatted according to the following description, and there will be no blank lines separating data sets.

A single data set has 4 components:
  1. Start line - A single line:
    START X

    where (1 <= X <= 20) is the number of contestants demanding shirts.
  2. Tolerance line - A single line containing X space-separated pairs of letters indicating the size tolerances of each contestant. Valid size letters are S - small, M - medium, L - large, X - extra large, T - extra extra large. Each letter pair will indicate the range of sizes that will satisfy a particular contestant. The pair will begin with the smallest size the contestant will accept and end with the largest. For example:
    MX

    would indicate a contestant that would accept a medium, large, or extra large T-shirt. If a contestant is very picky, both letters in the pair may be the same.
  3. Inventory line - A single line:
    S M L X T

    indicating the number of each size shirt in Boudreaux and Thibodeaux's inventory. These values will be between 0 and 20 inclusive.
  4. End line - A single line:
    END

After the last data set, there will be a single line:
ENDOFINPUT

Output

For each data set, there will be exactly one line of output. This line will reflect the attitude of the contestants after the T-shirts are distributed. If all the contestants were satisfied, output:

T-shirts rock!

Otherwise, output:
I'd rather not wear a shirt anyway...

Sample Input

START 1
ST
0 0 1 0 0
END
START 2
SS TT
0 0 1 0 0
END
START 4
SM ML LX XT
0 1 1 1 0
END
ENDOFINPUT

Sample Output

T-shirts rock!
I'd rather not wear a shirt anyway...
I'd rather not wear a shirt anyway...



很纯的二分匹配,把每一件衣服弄成一个节点即可,

二分匹配的过程是在寻找增广路,

https://img-my.csdn.net/uploads/201208/14/1344912634_2944.png

图1是我给出的二分图中的一个匹配:[1,5]和[2,6]。图2就是在这个匹配的基础上找到的一条增广路径:3->6->2->5->1->4。我们借由它来描述一下二分图中的增广路径的性质:

(1)有奇数条边。
(2)起点在二分图的左半边,终点在右半边。
(3)路径上的点一定是一个在左半边,一个在右半边,交替出现。(其实二分图的性质就决定了这一点,因为二分图同一边的点之间没有边相连,不要忘记哦。)
(4)整条路径上没有重复的点。
(5)起点和终点都是目前还没有配对的点,而其它所有点都是已经配好对的。(如图1、图2所示,[1,5]和[2,6]在图1中是两对已经配好对的点;而起点3和终点4目前还没有与其它点配对。)
(6)路径上的所有第奇数条边都不在原匹配中,所有第偶数条边都出现在原匹配中。(如图1、图2所示,原有的匹配是[1,5]和[2,6],这两条配匹的边在图2给出的增广路径中分边是第2和第4条边。而增广路径的第1、3、5条边都没有出现在图1给出的匹配中。)
(7)最后,也是最重要的一条,把增广路径上的所有第奇数条边加入到原匹配中去,并把增广路径中的所有第偶数条边从原匹配中删除(这个操作称为增广路径的取反),则新的匹配数就比原匹配数增加了1个。(如图2所示,新的匹配就是所有蓝色的边,而所有红色的边则从原匹配中删除。则新的匹配数为3。)

不难想通,在最初始时,还没有任何匹配时,图1中的两条灰色的边本身也是增广路径。因此在这张二分图中寻找最大配匹的过程可能如下:

(1)找到增广路径1->5,把它取反,则匹配数增加到1。
(2)找到增广路径2->6,把它取反,则匹配数增加到2。
(3)找到增广路径3->6->2->5->1->4,把它取反,则匹配数增加到3。
(4)再也找不到增广路径,结束。

当然,这只是一种可能的流程。也可能有别的找增广路径的顺序,或者找到不同的增广路径,最终的匹配方案也可能不一样。但是最大匹配数一定都是相同的。(http://blog.csdn.net/xuguangsoft/article/details/7861988)


下面给出代码:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;

#define MAXN (400+5)
#define Set(a, v) memset(a, v, sizeof(a))
#define For(i, a, b) for(int i = (a); i <= (b); i++)
#define Fort(i, a, b) for(int i = (a); i < (b); i++)

struct node{
	int s, t;
};

vector<int> G[MAXN];
int num[MAXN], size[150], link[MAXN];
node nodes[MAXN];
bool vis[MAXN];

void init(){
	For(i, 0, 401) G[i].clear();
}

bool dfs(int now){
	Fort(i, 0, G[now].size()){
		int v = G[now][i]; 
		if(vis[v]) continue;
		
		vis[v] = true;
		if(link[v] == -1 || dfs(link[v])){
			link[v] = now;
			return true;
		}
	}
	return false;
}

int huargy(int n){
	int ret = 0;
	
	Set(link, -1);
	For(i, 1, n){
		Set(vis, 0);
		
		vis[i] = true;
		ret += dfs(i);
	}
	return ret;
}

int main(){
	char tmp[20];
	
	size['S'] = 1; size['M'] = 2; size['L'] = 3; size['X'] = 4; size['T'] = 5;
	while(scanf("%s", tmp) != EOF){
		if(strlen(tmp) > 5) break;
		init();
		
		int n;
		scanf("%d", &n);
		
		For(i, 1, n){
			scanf("%s", tmp);
			nodes[i] = (node){size[tmp[0]], size[tmp[1]]};
		}
		
		num[0] = n;
		For(i, 1, 5){
			scanf("%d", &num[i]);
			num[i] += num[i-1];
		}
		scanf("%s", tmp);
		
		For(i, 1, n)
		  For(j, num[nodes[i].s-1]+1, num[nodes[i].t])
		      G[i].push_back(j);
		
		if(huargy(n) == n) printf("T-shirts rock!\n");
		else printf("I'd rather not wear a shirt anyway...\n");
	}
	
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值