题意:有N件T恤,N是6的倍数,因为有6种型号,每种件数相同,有M个人,每个人有两种型号的T恤适合他,每个人可以挑其中的一种,问能否所有的人都能分配到T恤。
解析:典型的二分图匹配,每N/6为同种T恤,对于单个人,将他与它适合的两种T恤的所有标号连边,最后计算最大匹配,如果小于M,则不可行,否则可行。
代码如下:
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<iterator>
#include<utility>
#include<sstream>
#include<iostream>
#include<cmath>
#include<stack>
using namespace std;
const int INF=1000000007;
const double eps=0.00000001;
vector<int> G[40];
int le[40],ri[40];
int N,M;
string type[]={"S","M","L","XS","XL","XXL"}; //6种型号的T恤
bool vis[40];
bool dfs(int cur) //二分图匹配模板
{
if(vis[cur]) return false;
vis[cur]=true;
for(int i=0;i<G[cur].size();i++)
{
int to=G[cur][i];
if(ri[to]==-1||dfs(ri[to]))
{
le[cur]=to;
ri[to]=cur;
return true;
}
}
return false;
}
bool Match()
{
int ret=0;
memset(le,-1,sizeof(le));
memset(ri,-1,sizeof(ri));
for(int i=1;i<=N;i++)
{
memset(vis,false,sizeof(vis));
if(dfs(i)) ret++; //如果能匹配,则加1
if(ret==M) return true; //达到M,直接返回真
}
return false;
}
int main()
{
int T;
cin>>T;
map<string,int> ma;
for(int i=0;i<6;i++) ma[type[i]]=i; //将T恤型号映射成编号
while(T--)
{
cin>>N>>M;
for(int i=1;i<=N;i++) G[i].clear();
int every=N/6;
string A,B;
for(int i=1;i<=M;i++)
{
cin>>A>>B;
int a=ma[A],b=ma[B];
for(int st=a*every+1;st<=(a+1)*every;st++) G[st].push_back(i); // 建立临接表,与所有为a的T恤的标号连边
for(int st=b*every+1;st<=(b+1)*every;st++) G[st].push_back(i);
}
if(Match()) printf("YES\n");
else printf("NO\n");
}
return 0;
}