题目转的有点远,不过如果对最大流问题比较熟悉的话也不难看出问题的本质。
下面描述建图过程。
1、设一个原点0,1到6为六种型号衣服对应的点,然后7到m+6是m个人对应的点,最后一个点m+7对应终结点。
2、原点到型号点的容量为n/6(根据题意),一个人对应两种型号衣服,每条线的容量都是1(每个人对应两种衣服),最后每个人到终点的容量都为1(每个人只需要一件衣服)。这样图就建好了。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <string>
#include <algorithm>
using namespace std;
const int N = 40;
const int inf = 1000000;
int n, m, T, s, t;
int cap[N][N], flow[N][N], p[N];
int maxFlow()
{
queue<int> q;
int ans = 0, a[N];
while(true)
{
q.push(s);
memset(a, 0, sizeof(a) );
a[s] = inf;
while (!q.empty())
{
int u = q.front(); q.pop();
for ( int i = 0; i <= t; ++i )
{
if ( !a[i] && cap[u][i] > flow[u][i] )
{
p[i] = u; q.push(i);
a[i] = min( a[u], cap[u][i] - flow[u][i] );
}
}
}
if ( a[t] == 0 )
break;
for ( int i = t; i != s; i = p[i] )
{
flow[p[i]][i] += a[t];
flow[i][p[i]] -= a[t];
}
ans += a[t];
}
return ans;
}
int num( string s )
{
if ( s == "XS" ) return 1;
else if ( s == "S") return 2;
else if ( s == "M") return 3;
else if ( s == "L") return 4;
else if ( s == "XL") return 5;
else if ( s == "XXL") return 6;
}
int main()
{
cin>>T;
while ( T-- )
{
cin>>n>>m;
s = 0, t = m + 7;
int f = n / 6;
memset(flow, 0, sizeof(flow));
memset(cap, 0, sizeof(cap));
for ( int i = 7; i <= 6 + m; ++i )
{
string a, b;
cin >> a >> b;
cap[num(a)][i] = 1;
cap[num(b)][i] = 1;
cap[i][t] = 1;
}
for ( int i = 1; i <= 6; ++i )
cap[0][i] += f;
int ans = maxFlow();
if (ans < m)
cout<<"NO"<<endl;
else
cout<<"YES"<<endl;
}
return 0;
}