4.X......XX......2XX.X3.X.X.X.X.3....XX.XX4................0 Sample Output51524题目大意:
给你一个n*n的矩阵,其中有一些点放置了障碍,然后问你最多放置多少的子使得每行每列有且只有一个除非中间有障碍
题目思路:
首先我们考虑最大匹配,但是中间有障碍也可以放,所以我们想到分成联通快,即某一行或某一列里最大相连通的快,然后进行编号,最后其实我们可以发现如果某一行出现了一个障碍物使得改行增加了一个联通快,实际上就相当于增加了一行,然后我们枚举所有点如果改点是空白点,就以改点的行列联通编号连边,最后进行最大匹配就是我们要求的答案
AC代码:
#include<cstring>#include<cstdio>const int maxn = 20;int link[maxn],a[maxn],b[maxn];bool vis[maxn],mp[maxn][maxn];int n,cnt,cnt1,flag,flag1;bool dfs(int u){ for(int i=1;i<=cnt1;i++){ if(!vis[i]&&mp[u][i]){ vis[i]=true; if(link[i]==-1||dfs(link[i])){ link[i]=u; return true; } } } return false;}int main(){ while(scanf("%d",&n),n){ memset(mp,false,sizeof(mp)); memset(link,-1,sizeof(link)); char str[5][5]; for(int i=0;i<n;i++)scanf("%s",str[i]); cnt=cnt1 = 1,flag=flag1=0; for(int i=0;i<n*n;i++){ int h = i/n,l=i%n; if(str[h][l]=='.')a[i]=cnt,flag=1; //a[i]记录改点的行联通编号 if(l==n-1||str[h][l]!='.') {if(flag)cnt++,flag=0;} //遇到障碍或一行的结束 if(str[l][h]=='.')b[l*n+h]=cnt1,flag1=1; //b[i]记录改点的列联通编号 if(l==n-1||str[l][h]!='.') {if(flag1)cnt1++,flag1=0;} //遇到障碍或一列的结束 } for(int i=0;i<n*n;i++)if(str[i/n][i%n]=='.')mp[a[i]][b[i]]=true; //改点的行联通编号和列联通编号连边 int ans = 0; for(int i=1;i<=cnt;i++){ memset(vis,false,sizeof(vis)); if(dfs(i))ans++; } printf("%d/n",ans); } return 0;}
新闻热点
疑难解答