题面
大秦 为你打开 题目传送门
题目翻译
一场NOI比赛即将举行。现在有X名队员,要给该些队员发放T恤。每名队员有一个合适的T恤尺码区间,然后给出每种尺码T恤的数目,问是否每个队员能分配到合适的尺码T恤。
T恤尺码由小到大依次是S(小号),M(中号),L(大号),X(特大号),T(超特大号)。
思路
那么显而易见的,这种队员和衣服对应的关系就是一张二分图,我们发现这里的 $N$ 实在是太太太小了,区区 $20$ ,我们直接用它给我们的区间大力建图,跑二分图最大匹配,搞定。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
| #include<bits/stdc++.h> using namespace std;
const int N = 510; const int M = 1010;
class Graph { private : struct Edge { int to, nt, wt; Edge() {} Edge(int to, int nt, int wt) : to(to), nt(nt), wt(wt) {} }e[M]; int hd[N], cnte; public : inline void AddEdge(int u, int v, int w = 0) { e[++cnte] = Edge(v, hd[u], w); hd[u] = cnte; } inline int head(int u) { return hd[u]; } inline int nt(int u) { return e[u].nt; } inline int to(int u) { return e[u].to; } inline int wt(int u) { return e[u].wt; } };
int n, m; char s[N]; int a[M][N];
Graph G; int vis[M], ma[M];
int Toint(char s) { if(s == 'S') return 1; if(s == 'M') return 2; if(s == 'L') return 3; if(s == 'X') return 4; return 5; }
void Input() { scanf("START %d", &n); for(int i = 1; i <= n; i++) { scanf("%s", s + 1); a[i][1] = Toint(s[1]); a[i][2] = Toint(s[2]); } int x; m = n; for(int i = 1; i <= 5; i++) { scanf("%d", &x); for(int j = m + 1; j <= m + x; j++) { for(int k = 1; k <= n; k++) { if(a[k][1] <= i && a[k][2] >= i) { G.AddEdge(j, k); } } } m += x; } scanf("%s", s); }
int Dfs(int u) { for(int i = G.head(u); i; i = G.nt(i)) { int v = G.to(i); if(vis[v]) continue; vis[v] = 1; if(!ma[v] || Dfs(ma[v])) { ma[v] = u; return 1; } } return 0; }
void Work() { int ans = 0; for(int i = 1; i <= m; i++) { memset(vis, 0, sizeof(vis)); if(Dfs(i)) ans++; } if(ans == n) { printf("YES\n"); } else { printf("NO\n"); } }
int main() { Input(); Work(); return 0; }
|