HDU 2819 ——Swap——————【最大匹配、利用linker数组、邻接表方式】
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”.
If it is impossible to make all the diagonal entries equal to 1, output only one one containing “-1”.
Sample Input
2
0 1
1 0
2
1 0
1 0
Sample Output
1
R 1 2
-1
题目大意:给你一个n*n的矩阵,里面只有0、1,问你需要几步可以让主对角线上全是1。如果不能实现,输出-1.
解题思路:如果想一想,画一画,可以发现,如果有行或者列全是0或1的话,那么结果肯定是-1。否则一定有解。按照常规的行列分部,在有1的行列进行连边。我们跑一遍最大匹配。如果最大匹配小于n,说明无解。否则利用匹配数组linker。这里linker[i]表示第i列跟第linker[i]行交点有数字1。那么我们枚举第i列。如果linker[i] != i,说明这个位置需要调换,然后暴力枚举linker[j] == i的j,交换linker[i],linker[j],同时记录路径即可。
#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> using namespace std; const int maxn = 1100; struct Edge{ int from, to, dist, next; Edge(){} Edge(int _from,int _to,int _next):from(_from),to(_to),next(_next){} }edges[maxn*maxn*3]; //direction struct Swap{ int x,y; }swaps[maxn*maxn]; int tot , head[maxn]; int linker[3*maxn], used[3*maxn], c[maxn]; void init(){ tot = 0; memset(head,-1,sizeof(head)); } void AddEdge(int _u,int _v){ edges[tot] = Edge(_u,_v,head[_u]); head[_u] = tot++; } bool dfs(int u,int _n){ for(int e = head[u]; e != -1; e = edges[e].next){ int v = edges[e].to; if(!used[v]){ used[v] = u; if(linker[v] == -1 || dfs(linker[v],_n)){ linker[v] = u; return true; } } } return false; } int hungary(int p, int n){ int ret = 0; memset(linker,-1,sizeof(linker)); for(int i = 1; i <= p; i++){ memset(used,0,sizeof(used)); if(dfs(i,n)) ret++; } return ret; } int main(){ int n, m, T, p, k, cas = 0; while(scanf("%d",&n)!=EOF){ int a,b; init(); for(int i = 1; i <= n; i++){ for(int j = 1; j <= n; j++){ scanf("%d",&a); if(a == 1){ AddEdge(i,j); } } } int ans = hungary(n,m); if(ans < n ){ puts("-1"); continue; } int num = 0; for(int i = 1; i <= n; i++){ if(linker[i] != i){ for(int j = i+1; j <= n; j++){ if(linker[j] == i){ swap(linker[i],linker[j]); num++; swaps[num].x = i; swaps[num].y = j; } } } } printf("%d\n",num); for(int i = 1; i <= num; i++){ printf("C %d %d\n",swaps[i].x,swaps[i].y); } } return 0; }
学学学 练练练 刷刷刷