HDU 2819 Swap(二分图匹配)

 

【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=2819

 

【题目大意】

  给出一个棋盘,由白格子和黑格子组成,可以交换棋盘的行列,
  使得其主对角线为黑格子,其余均为白格子,问是否能达成,
  如果能达成输出交换步骤,否则输出-1

 

【题解】

  我们对于所有的黑格子将其从属的行标和列标相连,做一遍二分图匹配,
  对于每一行拥有的黑块如果不是在对应的列,我们就将这一行和对应的行互换,

 

【代码】

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector> 
using namespace std;
const int MAX_V=2000;
int V,match[MAX_V];
vector<int> G[MAX_V];
bool used[MAX_V];
void add_edge(int u,int v){
    G[u].push_back(v);
    G[v].push_back(u);
}
bool dfs(int v){
    used[v]=1;
    for(int i=0;i<G[v].size();i++){
        int u=G[v][i],w=match[u];
        if(w<0||!used[w]&&dfs(w)){
            match[v]=u;
            match[u]=v;
            return 1;
        }
    }return 0;
}
int bipartite_matching(){
    int res=0;
    memset(match,-1,sizeof(match));
    for(int v=0;v<V;v++){
        if(match[v]<0){
            memset(used,0,sizeof(used));
            if(dfs(v))res++;
        }
    }return res;
}
const int MAX_N=1010;
int N,x,R[MAX_N],C[MAX_N];
void solve(){
    V=N*2;
    for(int i=0;i<V;i++)G[i].clear();
    for(int i=0;i<N;i++)for(int j=0;j<N;j++){
        scanf("%d",&x);
        if(x)add_edge(i,N+j);
    }
    if(bipartite_matching()!=N)puts("-1");
    else{
        printf("%d\n",N);
        for(int i=0;i<N;i++){
            R[match[i+N]+1]=i+1;
            C[i+1]=match[i+N]+1;
        }
        for(int i=1;i<=N;i++){
            printf("R %d %d\n",i,C[i]);
            C[R[i]]=C[i];
            R[C[i]]=R[i];
        }
    }
}
int main(){
    while(~scanf("%d",&N))solve();
    return 0;
}
posted @ 2017-04-06 17:04  forever97  阅读(139)  评论(0编辑  收藏  举报