UVA 11419 SAM I AM
2015-08-02 10:43
323 查看
SAM I AM
Time Limit: 7000msMemory Limit: 131072KB
This problem will be judged on UVA. Original ID: 11419
64-bit integer IO format: %lld Java class name: Main
The world is in great danger!! Mental's forces have returned to Earth to eradicate humankind. Our last hope to stop this great evil is Sam Serious Stone. Equipped with various powerful weapons, Serious Sam starts his mission to destroy the forces of evil.
After fighting two days and three nights, Sam is now in front of the temple KOPTOS where Mental's general Ugh Zan III is waiting for him. But this time, he has a serious problem. He is in shortage of ammo and a lot of enemies crawling inside the temple waiting for him. After rounding the temple Sam finds that the temple is in rectangle shape and he has the locations of all enemies in the temple.
All of a sudden he realizes that he can kill the enemies without entering the temple using the great cannon ball which spits out a gigantic ball bigger than him killing anything it runs into and keeps on rolling until it finally explodes. But the cannonball can only shoot horizontally or vertically and all the enemies along the path of that cannon ball will be killed.
Now he wants to save as many cannon balls as possible for fighting with Mental. So, he wants to know the minimum number of cannon balls and the positions from which he can shoot the cannonballs to eliminate all enemies from outside that temple.
Input
Here, the temple is defined as a RXC grid. The first line of each test case contains 3 integers: R(0<R<1001), C(0<C<1001) representing the grid of temple (R means number of row and C means number of column of the grid) and the number of enemies N(0<N<1000001) inside the temple. After that there are N lines each of which contains 2 integers representing the position of the enemies in that temple. Each test case is followed by a new line (except the last one). Input is terminated when R=C=N=0. The size of the input file is around 1.3 MB.Output
For each test case there will be one line output. First print the minimum number (m) of cannonballs needed to wipe out the enemies followed by a single space and then m positions from which he can shoot those cannonballs. For shooting horizontally print r followed by the row number and for vertical shooting print c followed by the column number. If there is more than one solution any one will do.Sample Input
4 4 31 1
1 4
3 2
4 4 2
1 1
2 2
0 0 0
Output for Sample Input
2 r1 r32 r1 r2
解题:最小点覆盖,最小点覆盖等于最大匹配数,关键在于如何把点覆盖中的点输出出来
来自Matrix67大神的解说
二分图最大匹配的König定理及其证明
本文将是这一系列里最短的一篇,因为我只打算把König定理证了,其它的废话一概没有。
以下五个问题我可能会在以后的文章里说,如果你现在很想知道的话,网上去找找答案:
1. 什么是二分图;
2. 什么是二分图的匹配;
3. 什么是匈牙利算法;(http://www.matrix67.com/blog/article.asp?id=41)
4. König定理证到了有什么用;
5. 为什么o上面有两个点。
König定理是一个二分图中很重要的定理,它的意思是,一个二分图中的最大匹配数等于这个图中的最小点覆盖数。如果你还不知道什么是最小点覆盖,我也在这里说一下:假如选了一个点就相当于覆盖了以它为端点的所有边,你需要选择最少的点来覆盖所有的边。比如,下面这个图中的最大匹配和最小点覆盖已分别用蓝色和红色标注。它们都等于3。这个定理相信大多数人都知道,但是网络上给出的证明并不多见。有一些网上常见的“证明”明显是错误的。因此,我在这里写一下这个定理的证明,希望对大家有所帮助。
#include <bits/stdc++.h> using namespace std; const int maxn = 1005; vector<int>g[maxn]; bool T[maxn],S[maxn]; int Link[maxn],n,m,k,Link2[maxn]; bool match(int u) { S[u] = true; for(int i = g[u].size()-1; i >= 0; --i) { if(!T[g[u][i]]) { T[g[u][i]] = true; if(Link[g[u][i]] == -1 || match(Link[g[u][i]])) { Link[g[u][i]] = u; Link2[u] = g[u][i]; return true; } } } return false; } int main() { int u,v; vector<int>X,Y; while(scanf("%d%d%d",&n,&m,&k),n||m||k) { for(int i = 0; i < maxn; ++i) g[i].clear(); for(int i = 0; i < k; ++i) { scanf("%d%d",&u,&v); g[u].push_back(v); } int ret = 0; memset(Link,-1,sizeof Link); memset(Link2,-1,sizeof Link2); for(int i = 1; i <= n; ++i) { memset(S,false,sizeof S); memset(T,false,sizeof T); if(match(i)) ++ret; } X.clear(); Y.clear(); memset(S,false,sizeof S); memset(T,false,sizeof T); for(int i = 1; i <= n; ++i) if(Link2[i] == -1) match(i); for(int i = 1; i <= n; ++i) if(!S[i]) X.push_back(i); for(int j = 1; j <= m; ++j) if(T[j]) Y.push_back(j); printf("%d",ret); for(int i = 0; i < X.size(); ++i) printf(" r%d",X[i]); for(int j = 0; j < Y.size(); ++j) printf(" c%d",Y[j]); putchar('\n'); } return 0; }
View Code
相关文章推荐
- Linux文件内容查阅 - cat, tac, nl, more, less, head, tail, od
- Android Service 访问安全
- Linux文件内容查阅 - cat, tac, nl, more, less, head, tail, od
- Android中对Log日志文件的分析
- wc命令
- 线程同步小结
- 8.2培训vector的使用
- MQ消息处理感悟
- 小灰的成长之路——第一周
- shell常用命令
- 【随笔】未来的路
- c++成员函数指针的应用
- VS2013 MFC opencv 播放视频
- Web富文本编辑器---UEditor
- java网络编程(7)——利用tcp实现文件上传
- Flash Player 19.0.0.124 Beta + IHTMLDocument3 IHTMLDocument2 ->get_innerHTML
- VS2013 MFC opencv 播放视频
- MVC出现错误:系统找不到指定文件(异常来自 HRSULT:0x80070002)
- HDU 1548 A strange lift
- JavaScript的基本语法