原题地址:点击打开链接
题意:一共有6种码号的衣服,每个人可以接受2种中的任意一个,每个衣服有n种颜色(本题与颜色无关,其实告诉你有n种颜色就是告诉你每个尺码有n件衣服),一共有
m个人,问这m个人能否都拿到适合自己的衣服。
思路:可用最大流求解,人为左边的点,衣服为右边的点,每个人与适合自己的衣服之间建边流量为1,源点与人之间建边流量为1,衣服与汇点之间建边流量为衣服的个数n。
如果求得的流量为m,则说明可以。
#include<stdio.h>
#include<string.h>
#include<vector>
#define INF 1<<31-1
#define min(x,y)(x<y?x:y)
using namespace std;
struct Edge
{
int to;
int cap;
int rev;
};
vector<Edge>g[210];
int used[210];
void add_edge(int from,int to,int cap)
{
g[from].push_back((Edge){to,cap,g[to].size()});
g[to].push_back((Edge){from,0,g[from].size()-1});
}
int dfs(int u,int t,int f)
{
if(u==t)
return f;
used[u]=1;
for(int i=0;i<g[u].size();i++)
{
Edge &e=g[u][i];
int v=e.to;
if(!used[v]&&e.cap>0)
{
int d=dfs(v,t,min(e.cap,f));
if(d>0)
{
e.cap-=d;
g[e.to][e.rev].cap+=d;
return d;
}
}
}
return 0;
}
bool max_flow(int s,int t,int m)
{
int res=0;
while(1)
{
memset(used,0,sizeof(used));
int d=dfs(s,t,INF);
if(d<=0)
break;
res+=d;
}
if(res==m) //如果能走2次就没必要在继续判断了
return true;
return false;
}
int getId(char s[])
{
if(strcmp(s,"XS")==0)
return 1;
if(strcmp(s,"S")==0)
return 2;
if(strcmp(s,"M")==0)
return 3;
if(strcmp(s,"L")==0)
return 4;
if(strcmp(s,"XL")==0)
return 5;
if(strcmp(s,"XXL")==0)
return 6;
}
int main()
{
int i,k=0,c,n,m,s,t;
char s1[5],s2[5];
scanf("%d",&c);
while(c--)
{
scanf("%d%d",&n,&m);
s=0;
t=m+6+1;
for(i=s;i<=t;i++)
g[i].clear();
for(i=1;i<=m;i++)
{
scanf("%s%s",s1,s2);
int id=getId(s1);
add_edge(i,id+m,1);
id=getId(s2);
add_edge(i,id+m,1);
}
for(i=1;i<=6;i++)
{
add_edge(i+m,t,n);
}
for(i=1;i<=m;i++)
{
add_edge(s,i,1);
}
if(max_flow(s,t,m))
printf("Case %d: YES\n",++k);
else
printf("Case %d: NO\n",++k);
}
return 0;
}
/*
3
3 6
L XL
XL L
XXL XL
S XS
M S
M L
1 4
S XL
L S
L XL
L XL
1 1
L M
1
1 2
L L
L L
*/