您的位置:首页 > 其它

[BZOJ]2150: 部落战争 二分图匹配

2017-09-12 13:36 239 查看
Description

lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国的下部征战来获得更大的领土。 A国是一个M*N的矩阵,其中某些地方是城镇,某些地方是高山深涧无人居住。lanzerb把自己的部落分成若干支军队,他们约定: 1. 每支军队可以从任意一个城镇出发,并只能从上往向下征战,不能回头。途中只能经过城镇,不能经过高山深涧。 2. 如果某个城镇被某支军队到过,则其他军队不能再去那个城镇了。 3. 每支军队都可以在任意一个城镇停止征战。 4. 所有军队都很奇怪,他们走的方法有点像国际象棋中的马。不过马每次只能走1*2的路线,而他们只能走R*C的路线。 lanzerb的野心使得他的目标是统一全国,但是兵力的限制使得他们在配备人手时力不从心。假设他们每支军队都能顺利占领这支军队经过的所有城镇,请你帮lanzerb算算至少要多少支军队才能完成统一全国的大业。

题解:

这个有向无环图为什么可以用二分图匹配呢?FYC大神告诉我:比如说对于一条路径1->2->3->4,直接建二分图,那么最后1、2、3都会找到匹配,最大匹配数为3。实际上,对于每一条路径,只有结尾的点没有匹配,其他的点都能找到匹配,所以每一个没有匹配的点实际上代表了一条路径,所以最小路径覆盖=总点数-最大匹配。

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=60;
int n,m,r,c,num[maxn][maxn],map[maxn][maxn],T=0;
char str[maxn];
int tx[10],ty[10];
bool in(int x,int y)
{
if(x>0&&y>0&&x<=n&y<=m)return true;
return false;
}
struct Edge{int y,next;}e[maxn*maxn*8];
int last[maxn*maxn],len=0,sum=0;
void ins(int x,int y)
{
int t=++len;
e[t].y=y;e[t].next=last[x];last[x]=t;
}
int chw[maxn*maxn],match[maxn*maxn];
bool findm(int x)
{
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(chw[y]!=T)
{
chw[y]=T;
if(!match[y]||findm(match[y]))
{
match[y]=x;
return true;
}
}
}
return false;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&r,&c);
tx[0]=tx[1]=r;tx[2]=tx[3]=c;
ty[0]=-c;ty[1]=c;ty[2]=-r;ty[3]=r;
for(int i=1;i<=n;i++)
{
scanf("%s",str+1);
for(int j=1;j<=m;j++)
map[i][j]=(str[j]=='.'?0:1);
}
int z=0,ans=0;
for(int i=1;i<=n;i++)
for(int j=1;
10198
j<=m;j++)
num[i][j]=++z;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(!map[i][j])
{
sum++;
for(int k=0;k<4;k++)
{
int x=i+tx[k],y=j+ty[k];
if(in(x,y)&&!map[x][y])ins(num[i][j],num[x][y]);
}
}
for(int i=1;i<=n*m;i++)
{
T++;
if(findm(i))ans++;
}
printf("%d",sum-ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: