zoukankan      html  css  js  c++  java
  • 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
    ",ans);
    72     return 0;
    73 }
  • 相关阅读:
    北风设计模式课程---22、责任链模式
    bootstarp modal自己主动调整宽度的JS代码
    谷歌技术面试要点(Google面试)(14年5月20日交大专场)
    ASCII与Unicode编码消息写文件浅析
    程序编写中的细节问题
    Oracle使用并行建索引须要注意的问题
    PHP读取Excel里的文件
    Oracle db中 CONNECT role的含义
    集团信息化之路—电子採购软件与现有库存及財务软件数据对接的探讨
    NTP方式保证以时间戳同步可靠性
  • 原文地址:https://www.cnblogs.com/guapisolo/p/9744375.html
Copyright © 2011-2022 走看看