hdu 3360 最小点覆盖 **

题意:给你一个图,图中有宝物和保安两种元素。每个宝物需要周围的某些位置同时安放保安(如果那些位置有宝物,可以把宝物替换成保安)问你最少需要再安置多少保安,可以使所有宝物满足要求。

题意有点难懂

链接:点我

直接建无向图,少判断个奇偶性,最后除个2即可

  1 #include<cstdio>

  2 #include<iostream>

  3 #include<algorithm>

  4 #include<cstring>

  5 #include<cmath>

  6 #include<queue>

  7 #include<map>

  8 using namespace std;

  9 #define MOD 1000000007

 10 const int INF=0x3f3f3f3f;

 11 const double eps=1e-5;

 12 typedef long long ll;

 13 #define cl(a) memset(a,0,sizeof(a))

 14 #define ts printf("*****\n");

 15 const int MAXN = 5010;//点数的最大值

 16 const int MAXM = 50010;//边数的最大值

 17 int a[MAXN][MAXN];

 18 int b[MAXN][MAXN];

 19 int n,m,tt;

 20 /*

 21 * 匈牙利算法邻接表形式

 22 * 使用前用init()进行初始化,给uN赋值

 23 * 加边使用函数addedge(u,v)

 24 *

 25 */

 26 struct Edge

 27 {

 28     int to,next;

 29 }edge[MAXM];

 30 int head[MAXN],tot;

 31 void init()

 32 {

 33     tot = 0;

 34     memset(head,-1,sizeof(head));

 35 }

 36 void addedge(int u,int v)

 37 {

 38     edge[tot].to = v; edge[tot].next = head[u];

 39     head[u] = tot++;

 40 }

 41 int linker[MAXN];

 42 bool used[MAXN];

 43 int uN;

 44 bool dfs(int u)

 45 {

 46     for(int i = head[u]; i != -1 ;i = edge[i].next)

 47     {

 48         int v = edge[i].to;

 49         if(!used[v])

 50         {

 51             used[v] = true;

 52             if(linker[v] == -1 || dfs(linker[v]))

 53             {

 54                 linker[v] = u;

 55                 return true;

 56             }

 57         }

 58     }

 59     return false;

 60 }

 61 int hungary()

 62 {

 63     int res = 0;

 64     memset(linker,-1,sizeof(linker));

 65     for(int u = 0; u < uN;u++)//点的编号0~uN-1

 66     {

 67         memset(used,false,sizeof(used));

 68         if(dfs(u))res++;

 69     }

 70     return res;

 71 }

 72 int dir[][2] = {{-1,-2},{-2,-1},{-2,1},{-1,2},{1,2},

 73 {2,1},{2,-1},{1,-2},{-1,0},{0,1},{1,0},{0,-1}};

 74 int main()

 75 {

 76     int i,j,k;

 77     #ifndef ONLINE_JUDGE

 78     freopen("1.in","r",stdin);

 79     #endif

 80     int ca=1;

 81     while(scanf("%d%d",&n,&m)!=EOF)

 82     {

 83         if(n==0&&m==0)  break;

 84         uN = 0;

 85         for(i = 0;i < n;i++)

 86             for(j = 0;j < m;j++)

 87             {

 88                 b[i][j] = uN++;

 89             }

 90         for(i=0;i<n;i++)

 91         {

 92             for(j=0;j<m;j++)

 93             {

 94                 scanf("%d",&a[i][j]);

 95             }

 96         }

 97         init();

 98         for(i=0;i<n;i++)

 99         {

100             for(j=0;j<m;j++)

101             {

102                 if(a[i][j]!=-1)

103                 {

104                     for(k=0;k<12;k++)

105                     {

106                         if(a[i][j]&(1<<k))  //该点需要放置守卫

107                         {

108                             int nx=i+dir[k][0];

109                             int ny=j+dir[k][1];

110                             if(nx>=0&&nx<n&&ny>=0&&ny<m&&a[nx][ny]!=-1)

111                             {

112                                 addedge(b[i][j],b[nx][ny]);

113                                 addedge(b[nx][ny],b[i][j]);

114                             }

115                         }

116                     }

117                 }

118             }

119         }

120         printf("%d. %d\n",ca++,hungary()/2);

121     }

122 }

 

你可能感兴趣的:(360)