标签:HDU 一个点 Fire long int bool Net include define
//只有出现墙的时候,才会出现一行/列多个点的情况
//那么可以考虑缩点,以行为例
//如果某一行没有墙,那么这一列整体所成一个点
//如果有墙,那么把没有墙的部分缩成一个点
//当换行时,记得点数++
#include<iostream>
#include<cstring>
#define INF 0x3f3f3f3f
#define LL long long
const int N=1000+5;
using namespace std;
int n;
bool st[N];//vis[i]表示是否在交替路中
int match[N];//存储连接点
int g[N][N];//存边
char str[N][N];
int x[N][N],cntX;//行点集
int y[N][N],cntY;//列点集
bool find(int x) {
for(int y=0; y<cntY; y++) { //对x的每个邻接点
if(g[x][y]==1&&!st[y]) { //不在交替路中
st[y]=true;//放入交替路
if(match[y]==-1 || find(match[y])) { //如果是未匹配点,说明交替路是增广路
match[y]=x;//交换路径
return true;//返回成功
}
}
}
return false;//不存在增广路,返回失败
}
int hungarian() {
int ans=0;//记录最大匹配数
memset(match,-1,sizeof match);
for(int i=1; i<=cntX; i++) { //从左侧开始每个结点找一次增广路
memset(st,false,sizeof st);
if(find(i))//找到一条增广路,形成一个新匹配
ans++;
}
return ans;
}
int main() {
while(scanf("%d",&n)!=EOF&&n) {
memset(x,0,sizeof(x));
memset(y,0,sizeof(y));
memset(g,false,sizeof(g));
for(int i=0; i<n; i++)
scanf("%s",str[i]);
//对行缩点
cntX=1;
for(int i=0; i<n; i++) {
for(int j=0; j<n; j++) {
if(str[i][j]=='.')//同一区域
x[i][j]=cntX;
if(str[i][j]=='X')//墙体阻隔
cntX++;
}
cntX++;//下一行
}
//对列缩点
cntY=1;
for(int j=0; j<n; j++) {
for(int i=0; i<n; i++) {
if(str[i][j]=='.')//同一区域
y[i][j]=cntY;
if(str[i][j]=='X')//墙体阻隔
cntY++;
}
cntY++;//下一列
}
//连边
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
if(str[i][j]=='.')
g[x[i][j]][y[i][j]]=true;
printf("%d\n",hungarian());
}
return 0;
}
标签:HDU,一个点,Fire,long,int,bool,Net,include,define 来源: https://www.cnblogs.com/QingyuYYYYY/p/12409549.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。