Time Limit: 1000MS | Memory Limit: 65536KB | 64bit IO Format: %lld & %llu |
Description
Input
A single data set has 4 components:
- Start line - A single line:
START X
where (1 <= X <= 20) is the number of contestants demanding shirts.
- 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.
- 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.
- End line - A single line:
END
After the last data set, there will be a single line:
ENDOFINPUT
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...
很纯的二分匹配,把每一件衣服弄成一个节点即可,
二分匹配的过程是在寻找增广路,
图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;
}