My T-shirt suits me
My T-shirt suits me |
Our friend Victor participates as an instructor in an environmental volunteer program. His boss asked Victor to distribute N T-shirts to M volunteers, one T-shirt each volunteer, where N is multiple of six, and NM. There are the same number of T-shirts of each one of the six available sizes: XXL, XL, L, M , S, and XS. Victor has a little problem because only two sizes of the T-shirts suit each volunteer.
You must write a program to decide if Victor can distribute T-shirts in such a way that all volunteers get a T-shirt that suit them. If N M, there can be some remaining T-shirts.
Input
The first line of the input contains the number of test cases. For each test case, there is a line with two numbers N and M. N is multiple of 6, 1N36, and indicates the number of T-shirts. Number M, 1M30, indicates the number of volunteers, with NM. Subsequently, M lines are listed where each line contains, separated by one space, the two sizes that suit each volunteer (XXL, XL, L, M , S, or XS).
Output
For each test case you are to print a line containing YES if there is, at least, one distribution where T-shirts suit all volunteers, or NO, in other case.
Sample Input
3 18 6 L XL XL L XXL XL S XS M S M L 6 4 S XL L S L XL L XL 6 1 L M
Sample Output
YES NO YES 思路:源点与每个人之间建一条容量为1的边,人与型号之间建立容量为1的边,型号与汇点建立容量为n/6的边,求最大流。 下面是代码:#include<iostream> #include<cstdio> #include<cstring> #include<string> using namespace std; const int maxn=50; const int INF=1000000000; struct node { int v,next,f; }edge[maxn*10]; int n,m,num,nn; int head[maxn],pre[maxn],gap[maxn],dis[maxn],vis[maxn],cur[maxn]; int change(string x) { if(x=="XXL")return m+1; else if(x=="XL") return m+2; else if(x=="L") return m+3; else if(x=="M") return m+4; else if(x=="S") return m+5; else if(x=="XS") return m+6; } void init() { num=0; memset(head,-1,sizeof(head)); } void add_edge(int x,int y,int f) { edge[num].v=y; edge[num].next=head[x]; edge[num].f=f; head[x]=num++; edge[num].v=x; edge[num].next=head[y]; edge[num].f=0; head[y]=num++; } int sap(int s,int t) { for(int i=0;i<=nn;i++) { dis[i]=gap[i]=0; cur[i]=head[i]; } int u,flow=0,aug=INF; gap[s]=nn; u=pre[s]=s; bool flag; while(dis[s]<nn) { flag=false; for(int &i=cur[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(edge[i].f>0&&dis[u]==dis[v]+1) { flag=1; if(edge[i].f<aug) aug=edge[i].f; pre[v]=u; u=v; if(u==t) { flow+=aug; while(u!=s) { u=pre[u]; edge[cur[u]].f-=aug; edge[cur[u]^1].f+=aug; } aug=INF; } break; } } if(flag)continue; int mindis=nn; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(dis[v]<mindis&&edge[i].f>0) { mindis=dis[v]; cur[u]=i; } } if((--gap[dis[u]])==0) break; gap[dis[u]=mindis+1]++; u=pre[u]; } return flow; } int main() { //freopen("in.txt","r",stdin); int t; string a,b; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); int s=0,e=m+7; nn=m+8; init(); for(int i=1;i<=m;i++) { cin>>a>>b; int x=change(a),y=change(b); add_edge(s,i,1); add_edge(i,x,1); add_edge(i,y,1); } for(int i=1;i<=6;i++) add_edge(m+i,e,n/6); int ans=sap(s,e); if(ans>=m)cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; }
还可以用二分图做#include <cstdio> #include <cstring> const int MAX = 300; int a[MAX][MAX]; int Match[MAX]; bool vis[MAX]; char str[7][10] = {"XXL","XL","L","M","S","XS"}; int n,m; int get(char *s) { for(int i = 0;i < 6; i++) { if(strcmp(s,str[i]) == 0) { return i + 1; } } } bool dfs(int u) { int i; for(i = i;i <= m; i++) { if(!a[u][i]) continue; if(vis[i]) continue; vis[i] = true; if(Match[i] == -1 || dfs(Match[i])) { Match[i] = u; return true; } } return false; } int match() { int ret = 0; int i; memset(Match,-1,sizeof(Match)); for(i = 1;i <= n; i++) { memset(vis,false,sizeof(vis)); if(dfs(i)) ret++; } return ret; } int main() { int t,i,j; char s1[10]; char s2[10]; scanf("%d",&t); while(t--) { scanf("%d %d",&n,&m); memset(a,0,sizeof(a)); for(i = 1;i <= m; i++) { scanf("%s %s",s1,s2); int id1 = get(s1); int id2 = get(s2); for(j = 0;j < n/6; j++) { a[id1+6*j][i] = 1; a[id2+6*j][i] = 1; } } if(match() == m) puts("YES"); else puts("NO"); } return 0; }