一道很裸的二分图匹配。
给每个外校学生以及每个不回家的本校学生都找一个床位,其中外校学生没有可用床位。
若所有人都能找到对应的床位,那么有可行解,否则无可行解。
要注意排除题目中的无效信息,否则它会变为错误信息。
Accode:
#include <cstdio> #include <cstdlib> #include <algorithm> const int maxN = 60; bool hvbd[maxN], gohm[maxN], marked[maxN]; //hvbd即have_bed,表示该学生是否为本校学生; //gohm即go_home,表示该学生是否回家。 int Link[maxN], mp[maxN][maxN], n, T; bool Find(int i) { for (int j = 0; j < n; ++j) if (mp[i][j] && !marked[j]) { marked[j] = 1; if (Link[j] == -1 || Find(Link[j])) { Link[j] = i; return 1; } } return 0; } int main() { freopen("holiday.in", "r", stdin); freopen("holiday.out", "w", stdout); for (scanf("%d", &T); T; --T) { scanf("%d", &n); for (int i = 0; i < n; ++i) { scanf("%d", hvbd + i); Link[i] = -1; //由于有多组数据,注意初值。 } for (int i = 0; i < n; ++i) scanf("%d", gohm + i); for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) { scanf("%d", mp[i] + j); if (i == j) mp[i][j] = 1; //if (gohm[i]) mp[i][j] = 0; //注意上面这句话不能要,因为如果该学生为外校学生, //那么gohm的标记就没有意义,并且导致错误。 if (!hvbd[j]) mp[i][j] = 0; } bool ok = 1; for (int i = 0; i < n; ++i) if (!hvbd[i] || hvbd[i] && !gohm[i]) { for (int j = 0; j < n; ++j) marked[j] = 0; //数组清零。 if (!Find(i)) { ok = 0; printf("T_T\n"); break; } } if (ok) printf("^_^\n"); } return 0; }