HDU - 2819
2 0 1 1 0 2 1 0 1 0Sample Output
1 R 1 2 -1
详细解释
我在代码中又具体解释了下路径输出的过程、
code:
#include
#include
#include
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 105
bool G[MAXN][MAXN],vis[MAXN];
int match[MAXN],N,M,T,a[MAXN],b[MAXN];
bool dfs(int u){
int i;
for(i = 0; i <= N; i++){
if(G[u][i] && !vis[i]){
vis[i] = true;
if(!match[i] || dfs(match[i])){
match[i] = u;
return true;
}
}
}
return false;
}
int main(){
while(~scanf("%d",&N)){
memset(G,0,sizeof(G));
memset(match,0,sizeof(match));
int x,ans = 0;
int i,j;
for(i = 1; i <= N; i++){
for(j = 1; j <= N; j++){
scanf("%d",&x);
if(x)
G[i][j] = true;
}
}
for(i = 1; i <= N; i++){
memset(vis,0,sizeof(vis));
if(dfs(i))
ans++;
}
//上面代码就是简单的求最大二分匹配的模板
if(ans < N){//如果最大二分匹配小于N,则说明矩阵的秩不是N,一定无法达到要求
printf("-1\n");
continue;
}
//以下是路径还原
int tot = 0;
//就目前来说,我们通过二分图最大匹配得到的match匹配数组只是证明这个矩阵的秩是n,可以通过
//交换得到,对角线都是1,并且已经记录下了匹配(即谁和谁进行交换),但是还没有进行交换
//实际上下面的任务只是根据match数组给我们指令,进行模拟交换一下就可以了,顺便记录下每次是
//谁和谁交换的即可
for(i = 1; i <= N; i++){//每个点都当做一个起点 (行号i)
for(j = 1; j <= N && match[j] != i; j++);//找到与之匹配的那个点(列号j)match[j]=i就是将j列的1移动到i列得到G[i][i]=1,完成一次交换
if(i != j){//只有当ij不相等才需要交换,如果相等说明原来这个点就在对角线上不用交换了
a[tot] = i;
b[tot] = j;//记录下交换的路径
tot++;
//交换完了,那就要真的交换过来,只需要交换match数组即可,就实现的j列和i列的交换,即j列现在对应了原来i列所对应的行号i',反之亦然
int t = match[i];
match[i] = match[j];
match[j] = t;
}
}
printf("%d\n",tot);
for(i = 0; i < tot; i++)
printf("C %d %d\n",a[i],b[i]);
//cout << "----------------------------------------------" << endl;
}
return 0;
}