题意:

N∗NN*NN∗N 的矩阵中有 KKK 个小行星,现在每行每列都有一个武器,可以消除此行或者此列中的所有小行星,问最少需要多少个武器可以将矩阵中所有小行星消除。


思路:

这是一个典型的最小点覆盖问题,可以用二分图匹配算法或者最大流算法进行解决 。我们主要来讨论网络流的做法。

先来回顾一下最大流 DinicDinicDinic 的基础性质,先在残量网络上 BFSBFSBFS 求出所有节点的层次,构造了一个分层图。然后在分层图上 DFSDFSDFS 寻找增广路,在回溯时实时更新剩余容量。当在残量网络中 SSS 不能到达 TTT 时,算法结束。

因此最大流这个算法有个很重要的性质,即最大流 === 最小割 === 最大匹配 === 最小点覆盖,基本覆盖了大部分最大流应用的题目。

现在我们再回过头来看这题如何建图,这题就是用最少的点覆盖所有的边,典型的最小点覆盖题目。因此我们将其转化为最大匹配,即每个点只能选择一次,最多选择多少条边。因此对于一个在 (i,j)(i,j)(i,j) 位置的行星,将左边第 iii 个点和右边第 jjj 个点相连,图中所有边流量均设为 111,跑最大流即可。

最后再来一个不严谨的 “最大匹配 === 最小点覆盖” 的证明。即当图中选的边已经达到了最大匹配之后,一定不存在一条未选的边,边的两个端点同时都没有被选。并且由于每个点只能被选择一次,因此每条边都代表只选了一个点,而这些点的集合覆盖了所有的边。不太严谨的证明,只是有利于记忆。详细证明可以网上继续查阅题解。


代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#define rep(i,a,b) for(int i = a;i <= b;i++)
using namespace std;
const int inf = 1<<29,N = 1000+10,M = 300500;  //处理1e4-1e5规模的网络struct Edge{ int to,next,v;
}e[M];
int n,m,s,t,k;  //顶点个数 边数 源点 汇点
int head[N],tot,dis[N],mp[N][N];
queue<int> q;void init()   //千万别忘了初始化!
{tot = 1; memset(head,0,sizeof head);  //点的编号是2~n,因为2^1 = 3, 3^1 = 2;  符合后续代码的操作
}void add(int x,int y,int v)
{e[++tot].to = y; e[tot].next = head[x]; e[tot].v = v; head[x] = tot;e[++tot].to = x; e[tot].next = head[y]; e[tot].v = 0; head[y] = tot;  //反向边与正向边的流量之和为v
}bool bfs()
{memset(dis,0,sizeof dis);while(!q.empty()) q.pop();q.push(s); dis[s] = 1;while(!q.empty()){int x = q.front(); q.pop();for(int i = head[x];i;i = e[i].next){if(e[i].v && !dis[e[i].to]){q.push(e[i].to);dis[e[i].to] = dis[x]+1;if(e[i].to == t) return 1;  //找到一条路就return }}}return 0;
}int dinic(int x,int flow) //找增广路
{if(x == t) return flow;int rest = flow,k;  //rest为输入的流量 for(int i = head[x];i && rest; i = e[i].next){if(e[i].v && dis[e[i].to] == dis[x]+1){k = dinic(e[i].to,min(rest,e[i].v));if(!k) dis[e[i].to] = 0;  //剪枝,去掉增广完毕的点 e[i].v -= k;e[i^1].v += k;  //反向边加上flow,相当于我们可以反悔从这条路流过 rest -= k; //k为能够被送出去的流量 }}return flow-rest;  //总共被送出去了多少流量
}int solve()
{int flow = 0,maxflow = 0;while(bfs())while((flow = dinic(s,inf))) maxflow += flow;    return maxflow;
}int main()
{while(~scanf("%d%d",&n,&k)){init();s = 1, t = 1+n+n+1;rep(i,1,k){int xx,yy; scanf("%d%d",&xx,&yy);add(xx+1,yy+1+n,1);}rep(i,1,n) add(s,i+1,1), add(1+n+i,t,1);printf("%d\n",solve());}return 0;
} /*
5 5
1 3
2 3
3 3
4 3
5 3
2
*/

【POJ 3041】Asteroids【网络流 —— 最小点覆盖】相关推荐

  1. POJ - 3041 Asteroids 二分图最小点覆盖

    题目链接 二分图一个很重要的定理:看了很多大神的博客表示看不懂为什么,以后再看 最小点覆盖=最大匹配 最小点覆盖就是在二分图里边,选择一个点,将所有与该点相链接的边删去,问最小找多少个点能够把所有的边 ...

  2. POJ 3041 Asteroids(最小点覆盖)题解

    题意:n*n的网格中有k个点,开一枪能摧毁一行或一列的所有点,问最少开几枪 思路:我们把网格看成两个集合,行集合和列集合,如果有点x,y那么就连接x->y,所以我们只要做最小点覆盖就好了. 参考 ...

  3. Asteroids POJ - 3041 匈牙利算法+最小点覆盖König定理

    题意: 给出一个N*N的地图N   地图里面有K个障碍     你每次可以选择一条直线 消除这条直线上的所有障碍  (直线只能和列和行平行) 问最少要消除几次 题解: 如果(x,y)上有一个障碍 则把 ...

  4. POJ 3041 Asteroids (对偶性,二分图匹配)

    题目:POJ 3041 Asteroids http://poj.org/problem?id=3041 分析: 把位置下标看出一条边,这显然是一个二分图最小顶点覆盖的问题,Hungary就好. 挑战 ...

  5. POJ 2226 Muddy Fields 最小点覆盖+加建图(好题)

    题目链接 题目一看就是最小点覆盖,这道题与POJ - 3041 算是一类题,但是3041算是一道十分裸的,因为删除的是整行或者整列,所以图其实是现成的,但是本题的难点就在如何建图. 思路:首先还是尽量 ...

  6. POJ 3041 Asteroids 二分图匹配

    以行列为点建图,每个点(x,y) 对应一条边连接x,y.二分图的最小点覆盖=最大匹配 //#pragma comment(linker, "/STACK:1024000000,1024000 ...

  7. POJ - 2226 Muddy Fields(最小点覆盖-二分图最大匹配)

    题目链接:点击查看 题目大意:给出一个n*m的地图,地图中'*'代表泥地,'.'代表空地,现在我们有两种木板,一种可以覆盖一行中的任意长度,我们成为行木板,另一种可以覆盖一列中的任意长度,我们成为列木 ...

  8. POJ - 3041 Asteroids(最小点覆盖-二分图最大匹配)

    题目链接:点击查看 题目分析:给出一个n*n的矩阵,其中有m个敌人,每一次操作可以清除某一列或某一行中的所有敌人,问若想清除所有敌人,至少需要多少次操作 题目分析:第一次见这种题,就是最小覆盖是要用最 ...

  9. POJ 3041 Asteroids (最小顶点覆盖)

    题目类型  最小顶点覆盖 题目意思 给出最多10000个点的坐标 每次可以消除同一行的点或同一列的点 问至少要多少次才能把所有点都消除掉 解题方法 首先建图 每一个行号为一个点 每一个列号为一个点 那 ...

  10. poj 3041 Asteroids

    这是一道二分匹配题,根据Konig定理:最大匹配数=最小覆盖数: 这里我们以行为左边,以列为右边建图,这样建好后,就是一个裸的二分匹配: View Code #include<iostream& ...

最新文章

  1. 算术表达式求解背景_1.8 C++算术运算符与表达式
  2. Python BaseHTTPServer 模块解析
  3. SAP FSM 学习笔记(二) : SAP FSM的微信接入
  4. ansible基本模块-shell
  5. 《Javascript权威指南》学习笔记之十二:数组、多维数组和符合数组(哈希映射)...
  6. CS229——线性回归
  7. jmeter正则表达式提取器_jmeter压测学习4正则表达式提取
  8. 【HAVENT原创】Spring Boot 跨命名空间调用外部依赖包
  9. libeigen3-dev和eigen有什么区别
  10. 姚舜:格力董明珠,一个女人的狼子野心
  11. 计算机上显示找不到无线网络连接,电脑上网时为什么只显示宽带连接不显示无线网络连接?...
  12. Java校验身份证号码合法性
  13. android实现第三方QQ登录
  14. 基于Android的健康宝体检app介绍(一)
  15. vgp虚拟路面_吉水县道路运输展示价格实惠
  16. java获取当前日期 星期几_java获取当前日期是星期几的方法
  17. 深度学习word2vec笔记之基础篇
  18. 华为设备ENSP基本命令简介
  19. 阿里云——OSS的创建和使用
  20. AW-Convlution:An Attention Module for Convolutional Neural Networks

热门文章

  1. 三目运算符?:结合性
  2. eclipse alt+/ 无效时,如何设置 《转》
  3. 强人Hibernate文档笔记(下)
  4. eclipse设置代码自动提示
  5. 如何让Html页面的导航固定在浏览器顶部
  6. 诺基亚n1支持java功能_关于诺基亚N1你必须要了解这10个问题!
  7. 缩放浏览器不会换行_深入解析 EventLoop 和浏览器渲染、帧动画、空闲回调的关系...
  8. BOBSLEDDING(一道有趣的贪心题 nyoj309)
  9. C++头文件的若干说明和const对象定义
  10. 软件技术PHp试卷,2014-2015软件技术学院AJAX试卷A