zoukankan      html  css  js  c++  java
  • hdu3360+二分匹配(匈牙利算法)

    有一个展厅,里面有一些文物和守卫,现在守卫不够,需要再雇佣一些守卫使所有文物被保护,且雇佣数量要最少,求这个数量。

    文物被保护的定义:这个文物的所有必须被保护的点都要有守卫。

                              一个文物由一个2的12次方以内的数表示,那么这个数最多有12位,对应图中给出打的12个可能要被保护的点。

                              从末位(i=0 to 11)开始,当i为1,则对应图中12个点中的第(i+1)个点必须被保护。

    构图:我们遍历每个文物,求出每个文物的必须被保护的点,向这个点与其对应的文物之间加边。

            显然,当图中每条边至少有一个点是有守卫的点,那么此时所有文物都被保护了。这便是求一个二分图的最小点覆盖,也即最大匹配数。

    细节:此题用邻接矩阵可能会超时或爆内存。可用邻接表。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<vector>
     4 using namespace std;
     5 int n,m;
     6 int dx[12]= {-1,-2,-2,-1,1,2,2,1,-1,0,1,0};
     7 int dy[12]= {-2,-1,1,2,2,1,-1,-2,0,1,0,-1};
     8 int a[60][60],linker[3600],vis[3600];
     9 vector<int> v[2550];
    10 bool dfs(int u)
    11 {
    12     int kk;
    13     for(kk=0;kk<v[u].size();kk++)
    14     {
    15         int vv=v[u][kk];
    16         if(!vis[vv])
    17         {
    18             vis[vv]=1;
    19             if(linker[vv]==-1||dfs(linker[vv]))
    20             {
    21                 linker[vv]=u;
    22                 return true;
    23             }
    24         }
    25     }
    26     return false;
    27 }
    28 int main()
    29 {
    30     int i,j,k,numcas=0;
    31     while(scanf("%d%d",&n,&m)!=EOF)
    32     {
    33         if(n==0&&m==0) break;
    34         for(i=0;i<n*m;i++)
    35             v[i].clear();
    36         for(i=0;i<n;i++)
    37             for(j=0;j<m;j++)
    38             scanf("%d",&a[i][j]);
    39         for(i=0;i<n;i++)
    40         {
    41             for(j=0;j<m;j++)
    42             {
    43                 if(a[i][j]!=-1)
    44                 {
    45                     for(k=0;k<12;k++)
    46                     {
    47                         if((a[i][j]>>k)&1)
    48                         {
    49                             int xx=i+dx[k];
    50                             int yy=j+dy[k];
    51                             if(xx>=0&&xx<n&&yy>=0&&yy<m&&a[xx][yy]!=-1)
    52                             {
    53                                 int p1=i*m+j;
    54                                 int p2=xx*m+yy;
    55                                 v[p1].push_back(p2);
    56                                 v[p2].push_back(p1);
    57                             }
    58                         }
    59                     }
    60                 }
    61             }
    62         }
    63         memset(linker,-1,sizeof(linker));
    64         int u,ret=0;
    65         for(u=0;u<n*m;u++)
    66         {
    67             memset(vis,0,sizeof(vis));
    68             if(dfs(u)) ret++;
    69         }
    70         printf("%d. %d
    ",++numcas,ret/2);
    71     }
    72     return 0;
    73 }
  • 相关阅读:
    PAT B1027 打印沙漏 (20 分)
    PAT B1025 反转链表 (25 分)
    PAT B1022 D进制的A+B (20 分)
    PAT B1018 锤子剪刀布 (20 分)
    PAT B1017 A除以B (20 分)
    PAT B1015 德才论 (25 分)
    PAT B1013 数素数 (20 分)
    PAT B1010 一元多项式求导 (25 分)
    HDU 1405 The Last Practice
    HDU 1165 Eddy's research II
  • 原文地址:https://www.cnblogs.com/mt522/p/5356643.html
Copyright © 2011-2022 走看看