BZOJ 2150 部落战争 (二分图匹配)

题目大意:给你一个n*m的棋盘,有一些坏点不能走,你有很多军队,每支军队可以像象棋里的马一样移动,不过马是1*2移动的,而军队是r*c移动的,军队只能从上往下移动,如果一个点已经被一直军队经过,那么其他军队不能再经过这个点,求覆盖所有非坏点的最少军队数

洛谷P2172传送门

对在某个点的军队可能跳的位置建边。把图抠出来,因为军队只能从上往下移动,所以他移动的方式就是是一条链,所以答案就是把这个图分成若干条链,求链的数量的最小值

这不就是二分图匹配么

对于一个链,除了端点,每个点都需要一个出边一个入边,跑匈牙利就行了

注意,每个点跑匈牙利之前都要清一次vis数组!才能正确表示某个点在这次匹配中是否已经被使用

 1 #include <queue>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #define N 60
 6 #define mod 20100403
 7 #define p(i,j) ((i-1)*m+j)
 8 #define dd double
 9 using namespace std;
10 
11 char str[N][N];
12 int n,m,r,c,cte;
13 int mp[N][N],head[N*N],vis[N*N],mch[N*N];
14 int xx[4],yy[4];
15 struct Edge{int to,nxt;}edge[N*N*10];
16 void ae(int u,int v){
17     ++cte,edge[cte].to=v;
18     edge[cte].nxt=head[u];
19     head[u]=cte;
20 }
21 int check(int x,int y){
22     if(x<1||y<1||x>n||y>m||mp[x][y]) return 0;
23     return 1;
24 }
25 void build_edge()
26 {
27     for(int i=1;i<=n;i++)
28         for(int j=1;j<=m;j++)
29         {
30             if(mp[i][j]) continue;
31             for(int k=0;k<4;k++)
32                 if(check(i+xx[k],j+yy[k]))
33                     ae(p(i,j),p(i+xx[k],j+yy[k]));
34         }
35 }
36 int Hungary(int x)
37 {
38     for(int j=head[x];j!=-1;j=edge[j].nxt){        
39         int v=edge[j].to;
40         if(!vis[v])
41         {
42             vis[v]=1;
43             if(!mch[v]||Hungary(mch[v])){
44                 mch[v]=x;
45                 return 1;
46             }
47         }
48     }return 0;
49 }
50 
51 
52 int main()
53 {
54     scanf("%d%d%d%d",&n,&m,&r,&c);
55     for(int i=1;i<=n;i++){
56         scanf("%s",str[i]+1);
57         for(int j=1;j<=m;j++)
58             if(str[i][j]=='.') mp[i][j]=0;
59             else mp[i][j]=1;
60     }
61     xx[0]=r,xx[1]=r,xx[2]=c,xx[3]=c;
62     yy[0]=c,yy[1]=-c,yy[2]=r,yy[3]=-r;
63     int ans=0;
64     memset(head,-1,sizeof(head));
65     build_edge();
66     for(int i=1;i<=n;i++)
67         for(int j=1;j<=m;j++){
68             if(mp[i][j]) continue;
69             memset(vis,0,sizeof(vis));
70             if(!Hungary(p(i,j))) ans++;}
71     printf("%d\n",ans);
72     return 0;
73 }

 

posted @ 2018-10-05 10:59  guapisolo  阅读(212)  评论(0编辑  收藏  举报