码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 3360 最小点覆盖

时间:2015-07-03 19:03:14      阅读:151      评论:0      收藏:0      [点我收藏+]

标签:

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

题意有点难懂

链接:点我

直接建无向图,少判断个奇偶性,最后除个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 }

 

hdu 3360 最小点覆盖

标签:

原文地址:http://www.cnblogs.com/cnblogs321114287/p/4619275.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!