您的位置:首页 > 其它

bzoj 2547: [Ctsc2002]玩具兵 bfs&最大匹配

2016-04-06 18:29 330 查看
在lrj的某一本书(蓝书?紫书?黑书?我不知道>_<)里面看到过。

首先可以把交换看成是更改职业,那么二分答案x,我们就得到了每个玩具兵(不包括天兵)可以到达的目标格。那么连一条边就得到一个二分图,跑最大匹配即可。

注意不能直接判断是否有完美匹配,还要考虑天兵,因为我们可以让天兵到x个地方然后作x次交换,那么在跑最大匹配的时候不把天兵加进去,然后判断是否有最大匹配数+x>=n即可。

AC代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define N 115
#define M 1005
using namespace std;

const int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
int m,n,cnt,pt,tot,c

,d

,path
,mp

;
struct node{ int x,y; }a
,b
,h[M+5]; bool bo
,inq

;
void bfs(int sx,int sy,int p){
memset(d,0x3f,sizeof(d)); d[sx][sy]=0;
int i,t,head=0,tail=1; node u,v;
h[1].x=sx; h[1].y=sy; memset(inq,0,sizeof(inq));
while (head!=tail){
head=head%M+1; u=h[head]; inq[u.x][u.y]=0;
for (i=0; i<4; i++){
v.x=u.x+dx[i]; v.y=u.y+dy[i];
if (v.x<=0 || v.x>m || v.y<=0 || v.y>n) continue;
if (p^(d[u.x][u.y]&1))
if (c[v.x][v.y]<=c[u.x][u.y]) t=0; else t=1;
else
if (c[v.x][v.y]>=c[u.x][u.y]) t=0; else t=1;
if (d[u.x][u.y]+t<d[v.x][v.y]){
d[v.x][v.y]=d[u.x][u.y]+t;
if (!inq[v.x][v.y]){ inq[v.x][v.y]=1; tail=tail%M+1; h[tail]=v; }
}
}
}
}
bool dfs(int x,int lim){
int i;
for (i=1; i<=tot; i++) if (bo[i] && mp[x][i]<=lim){
bo[i]=0;
if (!path[i] || dfs(path[i],lim)){
path[i]=x; return 1;
}
}
return 0;
}
bool ok(int x){
int i,tmp=0; memset(path,0,sizeof(path));
for (i=1; i<=(cnt<<1); i++){
memset(bo,1,sizeof(bo));
if (dfs(i,x)) tmp++;
}
return tmp+x>=(cnt<<1);
}
int main(){
scanf("%d%d%d%d",&m,&n,&cnt,&pt); int i,j,x,y,t;
for (i=1; i<=(cnt<<1|1); i++) scanf("%d%d",&a[i].x,&a[i].y);
for (i=1; i<=pt; i++){
scanf("%d%d%d",&x,&y,&t);
while (t--){ b[++tot].x=x; b[tot].y=y; }
}
for (i=1; i<=m; i++)
for (j=1; j<=n; j++) scanf("%d",&c[i][j]);
for (i=1; i<=(cnt<<1); i++){
if (i<=cnt) bfs(a[i].x,a[i].y,0); else bfs(a[i].x,a[i].y,1);
for (j=1; j<=tot; j++) mp[i][j]=d[b[j].x][b[j].y];
}
int l=0,r=cnt<<1,mid;
while (l<r){
mid=(l+r)>>1;
if (ok(mid)) r=mid; else l=mid+1;
}
printf("%d\n",l);
return 0;
}


by lych
2016.4.6
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: