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 }
时间: 2024-11-15 02:19:18

hdu 3360 最小点覆盖的相关文章

hdu 1054 最小点覆盖

Sample Input 4 0:(1) 1 1:(2) 2 3 2:(0) 3:(0) 5 3:(3) 1 4 2 1:(1) 0 2:(0) 0:(0) 4:(0) Sample Output 1 2 最小点覆盖=最大匹配数 水题,懒的拍了 1 #include<stdio.h> 2 #include<iostream> 3 #include<algorithm> 4 #include<string.h> 5 #include<vector>

I - Strategic Game - hdu 1054(最小点覆盖)

题意:用最小的点来覆盖全部的边,因为二分图里面最大的匹配就是最小覆盖,所以直接匹配一下即可 *********************************************************************** #include<stdio.h>#include<string.h>#include<queue>using namespace std; const int MAXN = 1505;const int oo = 1e9+7; stru

hdu 1150 最小点覆盖

题目大意;有两台机器A和B以及N个需要运行的任务.每台机器有M种不同的模式,而每个任务都恰好在一台机器上运行.如果它在机器A上运行,则机器A需要设置为模式xi,如果它在机器B上运行,则机器A需要设置为模式yi.每台机器上的任务可以按照任意顺序执行,但是每台机器每转换一次模式需要重启一次.请合理为每个任务安排一台机器并合理安排顺序,使得机器重启次数尽量少. 注意状态为0的即可 1 #include<cstdio> 2 #include<algorithm> 3 #include<

HDU 3360 National Treasures 奇偶匹配最小点覆盖

题目来源:HDU 3360 National Treasures 题意:如果a[i][j] != -1 把他转成二进制 最多有12位 代表题目那张图的12个位置 如果对应位是1 说明在那里放一个守卫可以看住a[i][j]位置上的这个东西 思路:明显死最小点覆盖 奇偶匹配建图 #include <cstdio> #include <cstring> #include <vector> using namespace std; const int maxn = 55; in

hdu 1054 Strategic Game 二分图最小点覆盖

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1054 题意: 给出一个无向图,求最小点覆盖. 思路: 用网络流来做设立一个超级源点和一个超级汇点. 每个点拆成i和i'. 从超级源点向点i连一条边,容量为1. 从i’向超级汇点连一条边,容量为1. 从i向i'连一条边,容量为正无穷. 然后求最小割/2.因为拆点拆成了2个. 也可以用二分图匹配来做,也是求出最大匹配然后/2. 1 #include <bits/stdc++.h> 2 using na

hdu 1151 或 poj 1422 二分图 最小点覆盖集

最小点覆盖集的裸题,只要“拆点建边”然后求出最大匹配,则:最小点覆盖集的大小 = 点数 - 最大匹配 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int N = 121; 7 const int M = 5000; 8 bool visit[N]; 9 int mark[N]; 10 int head[N]; 11 int

HDU 1498 50 years, 50 colors(最小点覆盖,坑题)

50 years, 50 colors Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1635    Accepted Submission(s): 892 Problem Description On Octorber 21st, HDU 50-year-celebration, 50-color balloons floating

HDU 3360-National Treasures(最小点覆盖+奇偶匹配)

/******************************************************* 题意: 现在有一个n*m的博物馆g,每一个g[i][j]要不是一个<=2^12 的数,要不就是-1. 如果这个点是-1,表示这个点有一个守卫 否则就是以g[i][j]为关键字规则的宝物. 具体规则是: 现在有12个被编号的点(题目中给出了图片),然后把g[i][j]表示成一个12位二进制数 ,从低位到高位(右到左)依次为1~12,如果某位i上是1,就表示在编号 为i的相对位置放置一个

HDU 1498 50 years, 50 colors(二分最大匹配之最小点覆盖)

题目地址:HDU 1498 晕啊...三个人同时做的这个题,结果全都理解错意思了..而且每个人理解错的地方还都不一样..但是样例还都能过,...简直炫酷... 题意:n*n的矩阵放置不同的颜色(不同的数字代表不同的颜色),你有k次选择,每一次只能选择某一行或某一列,可以消除该行(列)的所有颜色,问有哪几种颜色,无论怎样经过k次选择后依然无法完全抹去. 这个题的思路就是分别求出每种颜色的最少操作次数.然后只要大于k次的就是不符合要求的.然后输出就行了. #include <iostream> #