hdu2819 swap(二分图匹配)

来源:互联网 发布:布比网络 编辑:程序博客网 时间:2024/05/23 19:19

Description

Given an N*N matrix with each entry equal to 0 or 1. You can swap any two rows or any two columns. Can you find a way to make all the diagonal entries equal to 1?
 

Input

There are several test cases in the input. The first line of each test case is an integer N (1 <= N <= 100). Then N lines follow, each contains N numbers (0 or 1), separating by space, indicating the N*N matrix.
 

Output

For each test case, the first line contain the number of swaps M. Then M lines follow, whose format is “R a b” or “C a b”, indicating swapping the row a and row b, or swapping the column a and column b. (1 <= a, b <= N). Any correct answer will be accepted, but M should be more than 1000. 

If it is impossible to make all the diagonal entries equal to 1, output only one one containing “-1”. 

题意:给出一个0/1矩阵,问是否可以通过不断交换两行或两列得到一个左上右下对角线全是1的矩阵。如果可以,输出任意方案。(R a b交换a,b两行,C a b交换a,b两列)。有special judge,要求步骤数小于1000。

这题我一开始根本不觉得这和二分图有什么关系。。这几天搜索题做多了,第一反应是构造h函数。。然而这题确实巧妙。你可以先假定有一个主对角线全是1其他全是0的矩阵,然后乱交换几次看看,就有规律了:无论交换哪两行或者两列,得到的都是一个置换矩阵(每行每列仅一个1)。那么问题就显然是求原矩阵中是否包含一个置换矩阵。由于每行每列仅一个一,就将原图中所有行作为X部,列作为Y部,对矩阵中每个1将其行和列连边,检查是否满流即可。

至于输出方案,将那个置换矩阵取出来,再模拟一次给所有1的y坐标升序排序的过程即可。为了让交换次数尽量少,建议手写选择排序。


#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define MAXN 250#define MAXM 51000int N, M, cnt;int mat[MAXN][MAXN];struct Node { int to; Node*next; };struct BiGraph {    int match[MAXN], xn;    bool vis[MAXN];    Node Edge[MAXM*2], *ecnt, *adj[MAXN];    BiGraph() { memset(adj,0,sizeof adj); ecnt=Edge; }    void addedge(int a, int b)    {++ecnt;ecnt->to = b;ecnt->next = adj[a];adj[a] = ecnt;    }    bool dfs(int u)    {for (Node*p = adj[u]; p; p=p->next) {int &v = p->to;if (vis[v]) continue;vis[v] = 1;if (!match[v] || dfs(match[v])) {match[u] = v; match[v] = u;                return 1;}}return 0;    }    int Maxmatch()    {int ans = 0;for (int i = 1; i<=xn; ++i)if (!match[i]) {memset(vis, 0, sizeof vis);ans += dfs(i);}return ans;}} Empty, G;int a[MAXN];int x1[1000], x2[1000];int main(){int i, j;while (~scanf("%d", &N)) {G = Empty;G.xn = N;M = cnt = 0;for (i = 1; i<=N; ++i)for (j = 1; j<=N; ++j) {scanf("%d", &mat[i][j]);if (mat[i][j])G.addedge(i, j+N);}if (G.Maxmatch() < N) {puts("-1");continue;}for (i = 1; i<=N; ++i)for (j = 1; j<=N; ++j)if (mat[i][j] && G.match[i]==j+N)a[++cnt] = j;for (i = 1; i<=N; ++i) {if (a[i] == i) continue;for (j = i; j<=N; ++j)if (a[j] == i) {swap(a[i], a[j]);++M;x1[M] = i; x2[M] = j;break;}}printf("%d\n", M);for (i = 1; i<=M; ++i)printf("R %d %d\n", x1[i], x2[i]);}return 0;}





0 0
原创粉丝点击