UVA 11045-My T-shirt suits me(二分图匹配)

题意:有N件T恤,N是6的倍数,因为有6种型号,每种件数相同,有M个人,每个人有两种型号的T恤适合他,每个人可以挑其中的一种,问能否所有的人都能分配到T恤。

解析:典型的二分图匹配,每N/6为同种T恤,对于单个人,将他与它适合的两种T恤的所有标号连边,最后计算最大匹配,如果小于M,则不可行,否则可行。

代码如下:

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<iterator>
#include<utility>
#include<sstream>
#include<iostream>
#include<cmath>
#include<stack>
using namespace std;
const int INF=1000000007;
const double eps=0.00000001;
vector<int> G[40];
int le[40],ri[40];
int N,M;
string type[]={"S","M","L","XS","XL","XXL"}; //6种型号的T恤
bool vis[40];
bool dfs(int cur)    //二分图匹配模板
{
    if(vis[cur])  return false;
    vis[cur]=true;
    for(int i=0;i<G[cur].size();i++)
    {
        int to=G[cur][i];
        if(ri[to]==-1||dfs(ri[to]))
        {
            le[cur]=to;
            ri[to]=cur;
            return true;
        }
    }
    return false;
}
bool Match()
{
    int ret=0;
    memset(le,-1,sizeof(le));
    memset(ri,-1,sizeof(ri));
    for(int i=1;i<=N;i++)
    {
        memset(vis,false,sizeof(vis));
        if(dfs(i))  ret++;   //如果能匹配,则加1
        if(ret==M)  return true;  //达到M,直接返回真
    }
    return false;
}
int main()
{
    int T;
    cin>>T;
    map<string,int> ma;
    for(int i=0;i<6;i++)  ma[type[i]]=i;   //将T恤型号映射成编号
    while(T--)
    {
        cin>>N>>M;
        for(int i=1;i<=N;i++)  G[i].clear();
        int every=N/6;
        string A,B;
        for(int i=1;i<=M;i++)
        {
            cin>>A>>B;
            int a=ma[A],b=ma[B];
            for(int st=a*every+1;st<=(a+1)*every;st++)  G[st].push_back(i);  // 建立临接表,与所有为a的T恤的标号连边
            for(int st=b*every+1;st<=(b+1)*every;st++)  G[st].push_back(i);
        }
        if(Match())  printf("YES
");
        else  printf("NO
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/wust-ouyangli/p/4744227.html