hdu1498 50 years, 50 colors--匈牙利算法

来源:互联网 发布:公司网管必备软件 编辑:程序博客网 时间:2024/05/22 00:33

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1498


题意:一个n*n的矩阵,矩阵的每个格子放一个气球,气球颜色最多50种,编号1---50。对于每种颜色的气球,每次消去一行或者一列的该种颜色气球,问k次操作后,该颜色气球是否还存留,如果存留输出该气球编号。多种颜色气球存留的话,按编号大小升序输出;一个都不存在输出-1。


别人的题解都是最小点覆盖,我没看出来,但是单从匈牙利算法出发,这题还是可以理解的。一个巧妙之处就是match数组的作用,对于当前颜色,消去当前行,发现match[ 列坐标]!=-1的时候,说明该列存有相同颜色气球,那么如果if (dfs(match[v], color))成立,我们就要删除该列,而不是行,这是个转化问题,感觉好菜啊,,,继续努力吧。


#define _CRT_SECURE_NO_DEPRECATE #include<cstring>#include<iostream>#include<algorithm>#include<cmath>#include<queue>#include<vector>#define INF 99999999;using namespace std;int n, k;int a[105][105];bool color[55];//该颜色是否存在int match[105];bool vis[105];int dfs(int u, int color){for (int v = 0; v < n; v++){if (a[u][v] == color&&!vis[v]){vis[v] = true;if (match[v] == -1 || dfs(match[v], color)){match[v] = u;return 1;}}}return 0;}int hungarian(int color){int ans = 0;memset(match, -1, sizeof(match));for (int i = 0; i < n; i++){memset(vis, 0, sizeof(vis));ans += dfs(i, color);}return ans;}int main(){while (scanf("%d%d", &n, &k), n || k){memset(color, 0, sizeof(color));for (int i = 0; i < n; i++){for (int j = 0; j < n; j++){scanf("%d", &a[i][j]);color[a[i][j]] = 1;}}int p[55];//保存不能k次消除完的点int tol = 0;for (int i = 1; i <= 50; i++){if (color[i])//该颜色存在if (hungarian(i) > k)//注意匈牙利这里的参数赋值是i,不是color[i]p[tol++] = i;//注意是赋值i,不是赋值color[i]}if (tol == 0)printf("-1\n");else{sort(p, p + tol);for (int i = 0; i < tol; i++)(i == 0) ? printf("%d", p[i]) : printf(" %d", p[i]);printf("\n");}}return 0;}


1 0
原创粉丝点击