#include <stdio.h> #include <string.h> #define DEBUG #ifdef DEBUG #define debug(...) printf( __VA_ARGS__) #else #define debug(...) #endif #define N 301 char weight[101][N]; /* weight[x][y] = 1 表示学生x可以做课程y的助教 */ char mat[N]; /* mat[y] = x,表示定点y和x匹配 */ char visit[N]; int nx, ny; int find(int x) { int y; debug("go to X.%d\n", x); for (y = 1; y <= ny; y++) { if (!visit[y] && weight[x][y] > 0) { debug("go to Y.%d\n", y); visit[y] = 1; if (mat[y] == -1 || find(mat[y])) { debug("%d %d %d\n", x, y, mat[y]); /* 事实上程序实现的时候不用取反操作来标记哪些边已加入M,哪些边未加入M * 因为由mat数组和visit数组就可以确定,若mat[y] != -1, 则(mat[y],y)必然是一条加入M的边 * 只要visit[y] = 0,则(x,y)必然是一条没有加入M的边 if (mat[y] != -1) { weight[mat[y]][y] *= -1; } weight[x][y] *= -1; */ mat[y] = x; return 1; } debug("return from Y.%d\n", y); } } return 0; } int main() { int t, m, x, y, possible; scanf("%d", &t); while (t--) { memset(weight, 0, sizeof(weight)); memset(mat, -1, sizeof(mat)); scanf("%d %d", &nx, &ny); /* X集合是课程,Y集合是学生, 课程应比学生少 */ for (x = 1; x <= nx; x++) { scanf("%d", &m); while (m--) { scanf("%d", &y); weight[x][y] = 1; } } if (nx > ny) { printf("NO\n"); continue; } possible = 1; for (x = 1; x <= nx; x++) { memset(visit, 0, sizeof(visit)); if (!find(x)) { /* X集合只要有一个定点找不到增广路径,则图必然不是完备匹配 */ possible = 0; break; } debug("got an augmenting path...\n"); } if (possible) { printf("YES\n"); } else { printf("NO\n"); } } return 0; }
poj 1469 匈牙利算法求最大匹配
最新推荐文章于 2020-03-04 22:28:03 发布