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; }
愿你出走半生,归来仍是少年