题目大意:服装的种类有6中,现给出N件服装,M个自愿者,自愿者每人都能匹配2个尺码的服装,现在问每个自愿者是否都能得到匹配到服装
解题思路:弄一个超级源点,连接者6个点,这6个点分别对应这六种服装,源点到6个点的权值都为N/6,然后在设置一个汇点,M个自愿者连接到这个汇点,权值为1,因为每个自愿者只能匹配一件衣服。最后把每个自愿者连接到所能匹配的衣服的点,权值也为1,如图,图比较难看,请见谅
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define maxn 1100
#define INF 0x3f3f3f3f
int flow[maxn],q[maxn],head[maxn],v[maxn],next[maxn];
int N,M,d[maxn],e;
char str1[maxn];
void add(int a,int b,int w) {
v[e] = b;
flow[e] = w;
next[e] = head[a];
head[a] = e;
e++;
}
int bfs() {
memset(d,-1,sizeof(d));
int rear = 0;
q[rear++] = 0;
d[0] = 0;
for(int i = 0; i < rear; i++)
for(int j = head[q[i]]; j != -1; j = next[j])
if(d[v[j]] == -1 && flow[j]) {
d[v[j]] = d[q[i]] + 1;
// printf("v[j] is %d\n",v[j]);
if( v[j] == 1 )
return 1;
q[rear++] = v[j];
}
return 0;
}
int dfs(int cur,int a) {
if(cur == 1)
return a;
for(int i = head[cur]; i != -1; i = next[i])
if( d[v[i]] == d[cur] + 1 && flow[i]) {
if(int t = dfs(v[i],a < flow[i] ? a:flow[i])) {
flow[i] -= t;
flow[i^1] += t;
return t;
}
}
return 0;
}
void init(int t) {
memset(head,-1,sizeof(head));
e = 0;
add(0,2,t);
add(2,0,0);
add(0,3,t);
add(3,0,0);
add(0,4,t);
add(4,0,0);
add(0,5,t);
add(5,0,0);
add(0,6,t);
add(6,0,0);
add(0,7,t);
add(7,0,0);
}
int EK() {
int ans = 0, t;
while(bfs()) {
while(t = dfs(0,INF)) {
ans += t;
}
}
return ans;
}
int main() {
int test;
scanf("%d",&test);
while(test--) {
scanf("%d%d",&N,&M);
int t1;
init(N / 6);
for(int i = 0; i < M; i++) {
for(int j = 0; j < 2; j++) {
scanf("%s",str1);
if(strcmp(str1,"XXL") == 0)
t1 = 2;
else if(strcmp(str1,"XL") == 0)
t1 = 3;
else if(strcmp(str1,"L") == 0)
t1 = 4;
else if(strcmp(str1,"M") == 0)
t1 = 5;
else if(strcmp(str1,"S") == 0)
t1 = 6;
else if(strcmp(str1,"XS") == 0)
t1 = 7;
add(t1,i+8,1);
add(i+8,t1,0);
}
add(i+8,1,1);
add(1,i+8,0);
}
if(M - EK() == 0)
printf("YES\n");
else
printf("NO\n") ;
}
return 0;
}