题目转的有点远,不过如果对最大流问题比较熟悉的话也不难看出问题的本质。
下面描述建图过程。
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; }