【POJ 3041】Asteroids【网络流 —— 最小点覆盖】
题意:
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【网络流 —— 最小点覆盖】相关推荐
- POJ - 3041 Asteroids 二分图最小点覆盖
题目链接 二分图一个很重要的定理:看了很多大神的博客表示看不懂为什么,以后再看 最小点覆盖=最大匹配 最小点覆盖就是在二分图里边,选择一个点,将所有与该点相链接的边删去,问最小找多少个点能够把所有的边 ...
- POJ 3041 Asteroids(最小点覆盖)题解
题意:n*n的网格中有k个点,开一枪能摧毁一行或一列的所有点,问最少开几枪 思路:我们把网格看成两个集合,行集合和列集合,如果有点x,y那么就连接x->y,所以我们只要做最小点覆盖就好了. 参考 ...
- Asteroids POJ - 3041 匈牙利算法+最小点覆盖König定理
题意: 给出一个N*N的地图N 地图里面有K个障碍 你每次可以选择一条直线 消除这条直线上的所有障碍 (直线只能和列和行平行) 问最少要消除几次 题解: 如果(x,y)上有一个障碍 则把 ...
- POJ 3041 Asteroids (对偶性,二分图匹配)
题目:POJ 3041 Asteroids http://poj.org/problem?id=3041 分析: 把位置下标看出一条边,这显然是一个二分图最小顶点覆盖的问题,Hungary就好. 挑战 ...
- POJ 2226 Muddy Fields 最小点覆盖+加建图(好题)
题目链接 题目一看就是最小点覆盖,这道题与POJ - 3041 算是一类题,但是3041算是一道十分裸的,因为删除的是整行或者整列,所以图其实是现成的,但是本题的难点就在如何建图. 思路:首先还是尽量 ...
- POJ 3041 Asteroids 二分图匹配
以行列为点建图,每个点(x,y) 对应一条边连接x,y.二分图的最小点覆盖=最大匹配 //#pragma comment(linker, "/STACK:1024000000,1024000 ...
- POJ - 2226 Muddy Fields(最小点覆盖-二分图最大匹配)
题目链接:点击查看 题目大意:给出一个n*m的地图,地图中'*'代表泥地,'.'代表空地,现在我们有两种木板,一种可以覆盖一行中的任意长度,我们成为行木板,另一种可以覆盖一列中的任意长度,我们成为列木 ...
- POJ - 3041 Asteroids(最小点覆盖-二分图最大匹配)
题目链接:点击查看 题目分析:给出一个n*n的矩阵,其中有m个敌人,每一次操作可以清除某一列或某一行中的所有敌人,问若想清除所有敌人,至少需要多少次操作 题目分析:第一次见这种题,就是最小覆盖是要用最 ...
- POJ 3041 Asteroids (最小顶点覆盖)
题目类型 最小顶点覆盖 题目意思 给出最多10000个点的坐标 每次可以消除同一行的点或同一列的点 问至少要多少次才能把所有点都消除掉 解题方法 首先建图 每一个行号为一个点 每一个列号为一个点 那 ...
- poj 3041 Asteroids
这是一道二分匹配题,根据Konig定理:最大匹配数=最小覆盖数: 这里我们以行为左边,以列为右边建图,这样建好后,就是一个裸的二分匹配: View Code #include<iostream& ...
最新文章
- 算术表达式求解背景_1.8 C++算术运算符与表达式
- Python BaseHTTPServer 模块解析
- SAP FSM 学习笔记(二) : SAP FSM的微信接入
- ansible基本模块-shell
- 《Javascript权威指南》学习笔记之十二:数组、多维数组和符合数组(哈希映射)...
- CS229——线性回归
- jmeter正则表达式提取器_jmeter压测学习4正则表达式提取
- 【HAVENT原创】Spring Boot 跨命名空间调用外部依赖包
- libeigen3-dev和eigen有什么区别
- 姚舜:格力董明珠,一个女人的狼子野心
- 计算机上显示找不到无线网络连接,电脑上网时为什么只显示宽带连接不显示无线网络连接?...
- Java校验身份证号码合法性
- android实现第三方QQ登录
- 基于Android的健康宝体检app介绍(一)
- vgp虚拟路面_吉水县道路运输展示价格实惠
- java获取当前日期 星期几_java获取当前日期是星期几的方法
- 深度学习word2vec笔记之基础篇
- 华为设备ENSP基本命令简介
- 阿里云——OSS的创建和使用
- AW-Convlution:An Attention Module for Convolutional Neural Networks
热门文章
- 三目运算符?:结合性
- eclipse alt+/ 无效时,如何设置 《转》
- 强人Hibernate文档笔记(下)
- eclipse设置代码自动提示
- 如何让Html页面的导航固定在浏览器顶部
- 诺基亚n1支持java功能_关于诺基亚N1你必须要了解这10个问题!
- 缩放浏览器不会换行_深入解析 EventLoop 和浏览器渲染、帧动画、空闲回调的关系...
- BOBSLEDDING(一道有趣的贪心题 nyoj309)
- C++头文件的若干说明和const对象定义
- 软件技术PHp试卷,2014-2015软件技术学院AJAX试卷A