uva 11045 My T-shirt suits me (二分图匹配 最大流)

uva 11045 My T-shirt suits me

题目大意:有n件衣服(一定是6的倍数,六种尺码n / 6套),m个试穿者,每个试穿者都有两种合适的尺码(尺码一共有六种:XS, S, M, L, XL, XXL)。问是否所有试穿者都能找到合适的衣服。

解题思路:设置一个超级源点,连向所有的试穿者,容量为1。把相同的衣服,当成不同的,比如XS型号的衣服有三件,我们则把它分为编号为1, 1 + 6, 1 + 12三件衣服。这样所有的衣服连向一个超级汇点,容量为一。然后把顾客和相应尺寸的衣服连起来(记得是同尺寸的所有衣服)。最后求最大流。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <map>
#include <iostream>
#include <queue>
using namespace std;
typedef long long ll;
const int N = 305;
const int INF = 0x3f3f3f3f;
const int OF = 50;
int n, m, L, s, t, rec[N];
map<string, int> mp2;
string size[7] = {"", "XS", "S", "M", "L", "XL", "XXL"};
struct Edge{
    int from, to, cap, flow;
};

vector<Edge> edges;
vector<int> G[N];

void init() {
    memset(rec, 0, sizeof(rec));
    for (int i = 0; i < N; i++) G[i].clear();
    edges.clear();
}
void addEdge(int from, int to, int cap, int flow) {
    edges.push_back((Edge){from, to, cap, 0});
    edges.push_back((Edge){to, from, 0, 0});
    int m = edges.size();
    G[from].push_back(m - 2);
    G[to].push_back(m - 1);
}
void input() {
    mp2[size[1]] = 1;
    mp2[size[2]] = 2;
    mp2[size[3]] = 3;
    mp2[size[4]] = 4;
    mp2[size[5]] = 5;
    mp2[size[6]] = 6;
    for (int i = 1; i <= m; i++) {
        addEdge(0, i, 1, 0);
    }
    string a, b;
    for (int i = 1; i <= m; i++) {
        cin >> a >> b;
        for (int j = 0; j < L; j++) {
            int pa = mp2[a] + OF + j * 6;
            addEdge(i, pa, 01, 0);
            if (!rec[pa]) {
                addEdge(pa, t, 1, 0);
                rec[pa] = 1;
            }
            int pb = mp2[b] + OF + j * 6;
            addEdge(i, pb, 1, 0);
            if (!rec[pb]) {
                addEdge(pb, t, 1, 0);
                rec[pb] = 1;
            }
        }
    }
}
int vis[N], d[N];
int BFS() {
    memset(vis, 0, sizeof(vis));
    queue<int> Q;
    Q.push(s);
    d[s] = 0;
    vis[s] = 1;
    while (!Q.empty()) {
        int u = Q.front(); Q.pop();
        for (int i = 0; i < G[u].size(); i++) {
            Edge &e = edges[G[u][i]];
            if (!vis[e.to] && e.cap > e.flow) {
                vis[e.to] = 1;
                d[e.to] = d[u] + 1;
                Q.push(e.to);
            }
        }
    }
    return vis[t];
}

int cur[N];
int DFS(int u, int a) {
    if (u == t || a == 0) return a;
    int flow = 0, f;
    for (int &i = cur[u]; i < G[u].size(); i++) {
        Edge &e = edges[G[u][i]];
        if (d[u] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0) {
            e.flow += f;
            edges[G[u][i]^1].flow -= f;
            flow += f;
            a -= f;
            if (a == 0) break;
        }
    }
    return flow;
}
int MF() { //dinic算法求最大流
    int ans = 0;
    while (BFS()) {
        memset(cur, 0, sizeof(cur));
        ans += DFS(s, INF);
    }
    return ans;
}
int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%d %d", &n, &m);
        s = 0, t = 200;
        L = n / 6;
        init();
        input();
        int ans;
        ans = MF();
        if (ans == m) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-07 12:06:00

uva 11045 My T-shirt suits me (二分图匹配 最大流)的相关文章

cogs_14_搭配飞行员_(二分图匹配+最大流,网络流24题#01)

描述 http://cojs.tk/cogs/problem/problem.php?pid=14 有一些正飞行员和副飞行员,给出每个正飞行员可以和哪些副飞行员一起飞.一架飞机上必须一正一副,求最多多少飞机可以飞. 分析 裸的二分图匹配... 请叫我水题小王子... 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=100+5,INF=0x7fffffff; 5 int n,m,cnt=1; 6 int l

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> #

UVA 11419 - SAM I AM(二分图匹配+最小点覆盖)

UVA 11419 - SAM I AM 题目链接 题意:给定一个棋盘,上面有一些目标,现在要放炮,一个炮能打一行或一列,问最少放几个炮及放炮位置 思路:首先是二分图匹配,每个目标行列建边,做二分图匹配就是最少的放炮位置,至于输出方案,利用最小点覆盖的Konig原理去做,详细证明 代码: #include <cstdio> #include <cstring> #include <vector> using namespace std; const int N = 10

uva 12083 Guardian of Decency (二分图匹配)

uva 12083 Guardian of Decency Description Frank N. Stein is a very conservative high-school teacher. He wants to take some of his students on an excursion, but he is afraid that some of them might become couples. While you can never exclude this poss

UVA 12168 - Cat vs. Dog(二分图匹配+最大独立集)

UVA 12168 - Cat vs. Dog 题目链接 题意:给定一些猫爱好者,和一些狗爱好者,每个人都有一个喜欢的猫(狗),和一个讨厌的狗(猫),要问现在给一种方案,使得尽量多的人被满足 思路:二分图匹配最大独立集,猫爱好者和狗爱好者矛盾的建边,做一次最大独立集即可 代码: #include <cstdio> #include <cstring> #include <vector> using namespace std; const int N = 505; in

POJ2584 T-Shirt Gumbo 二分图匹配(网络流)

1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 const int inf=0x3f3f3f3f; 6 const int sink=30; 7 8 struct Edge 9 { 10 int to; 11 int next; 12 int capacity; 13 14 void assign(int t,int n,int c) 15 { 16 to=t; next=n; ca

棋盘游戏(二分图匹配)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1281 棋盘游戏 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3200    Accepted Submission(s): 1897 Problem Description 小 希和Gardon在玩一个游戏:对一个N*M的棋盘,在格子里放

BZOJ 1854 游戏(二分图匹配或并查集)

此题的二分图匹配做法很容易想,就是把属性当做s集,武器当做t集,如果该武器拥有该武器则连一条边. 那么答案就是求该二分图的最大前i个匹配.将匈牙利算法改一改,当前找不到增广路就break. 但是过这个题需要常数优化,不能每次都fillchar一遍used数组.可以用队列将使用的used点加入,然后需要初始化的时候弹出即可. # include <cstdio> # include <cstring> # include <cstdlib> # include <i

HDU 3081:Marriage Match II(二分图匹配+并查集)

http://acm.hdu.edu.cn/showproblem.php?pid=3081 题意:有n个男生n个女生,他们只有没有争吵或者女生a与男生A没有争吵,且女生b与女生a是朋友,因此女生b也可以和男生A过家家(具有传递性).给出m个关系,代表女生a和男生b没有争吵过.给出k个关系,代表女生a与女生b是好朋友.每一轮过家家之后,女生只能选择可以选择并且没选过的男生过家家,问游戏能进行几轮. 思路:因为n<=100,因此支持O(n^3)的算法,挺容易想到是一个二分图匹配的.(出现在我的网络