来更新一篇blog吧
最近做了一下hackerrank的20/20的比赛。平时都只能过2题,这周顺利地通过了四道题目竟然。当妄图冲击衬衫的时候,发现剩下三个题一点招数都没有,之后就跑去看了一下node.js了。。。
这次比赛的第四个题目是用cpp敲的,之前都是偷懒用python。
Bike Racers
【题意描述】
在城市里有n个骑车的人,有m辆自行车,人可以同时沿着任意方向行走,每单位时间移动单位距离。要求出前k个到达自行车的人所花费的最小时间。人和自行车都用整数坐标表示。
1 <= N <= 250
1 <= M <= 250
1 <= K <= min(N,M)
0 <= xi,yi <= 107
【思路】
这一个题目,拿到之后没什么想法。然后感觉应该像是二分图的匹配问题。然后就去恶补了二分图,刷了三四道题目。第二天晚上回来,发现确实是二分图……那么大意就是求出这个图的一个子图,这个子图的二分图匹配数为k并且匹配的边中最大值最小。
那么这道题可以用类似克鲁斯卡尔最小生成树的问题来解决。将边从小到大进行排序,依次添加到图中。每次添加检测匹配数,当匹配数为k的时候,最后添加的那条边就是所求解。匹配当然是采用匈牙利算法进行。
算法确定,之后就是数据结构的问题:
如何保存图是本题的关键。
假设边以经按照权值排序完成。加边只修要O(1)的时间。
题目的总体复杂度为V*匈牙利算法的复杂度(V为边数)
匈牙利算法的复杂度为DFS的复杂度V*E(边数*点数)
通常的题目中,使用邻接矩阵来保存图,匈牙利算法就退化成为了E*E*E(V=E*E),于是总体复杂度就变成了E^5。必须会TLE。
世界就是如此美好,这个时候如果用边表来保存整个图,那么每次匈牙利算法的复杂度仍旧是V*E,总体复杂度就变为了(E*1+E*2+……+E*E*E)=1/2*(E^3)*(E+1)大约为E^4。看上去好很多了。
排序的优化:
为了让算法看上去更快一点,我又对排序这个地方产生了想法,如果排序的话,排序的复杂度为:
V*logV = E*E*log(E*E) = 2E*ElogE。在最坏的情况下,加入了最后一条边才能出结果,这个时候复杂度是不会有改善的。这里考虑平均情况,也就是说不需要每次都用到所有的边,这个时候使用小顶堆可以胜任!
以下是拙劣的代码。窃喜一下,还是觉得有长进的…
- 1: #include <iostream>
- 2: #include <cstring>
- 3: #include <algorithm>
- 4: #include <queue>
- 5:
- 6: using namespace std;
- 7:
- 8: struct Point {
- 9: long long x,y;
- 10: Point( long long _x, long long _y ) {
- 11: x = _x;
- 12: y = _y;
- 13: }
- 14: Point() {}
- 15: long long dis( Point p ) {
- 16: long long lx = x - p.x;
- 17: long long ly = y - p.y;
- 18: lx *= lx;
- 19: ly *= ly;
- 20: return lx+ly;
- 21: }
- 22: };
- 23:
- 24: struct Edge {
- 25: int y,next;
- 26: long long l;
- 27: Edge ( int _y, long long _l, int _next ) {
- 28: y = _y;
- 29: next = _next;
- 30: l = _l;
- 31: }
- 32: Edge () {}
- 33: };
- 34:
- 35: struct E{
- 36: int x,y;
- 37: long long l;
- 38: E( int _x, int _y, long long _l ) {
- 39: x = _x;
- 40: y = _y;
- 41: l = _l;
- 42: }
- 43: E(){}
- 44: bool operator<( const E &e ) const {
- 45: return l > e.l;
- 46: }
- 47: };
- 48:
- 49: const int MAXSIZE = 255;
- 50: const int NC = MAXSIZE*2;
- 51:
- 52: priority_queue<E> Q;
- 53:
- 54: int head[NC];
- 55: Edge e[MAXSIZE*MAXSIZE];
- 56: Point p[MAXSIZE];
- 57: int visited[NC];
- 58: int mark[NC];
- 59:
- 60:
- 61: int e_len;
- 62: int n,m,k;
- 63: long long last;
- 64:
- 65: void add( E ex ) {
- 66: e[e_len] = Edge(ex.y,ex.l,head[ex.x]);
- 67: head[ex.x] = e_len++;
- 68: }
- 69:
- 70: void input() {
- 71: while ( !Q.empty() ) {
- 72: Q.pop();
- 73: }
- 74: memset(e,-1,sizeof(e));
- 75: memset(head,-1,sizeof(head));
- 76: memset(p,0,sizeof(p));
- 77: e_len = 0;
- 78: cin>>n>>m>>k;
- 79: for ( int i = 0; i < n; i++ ) {
- 80: long long x,y;
- 81: cin>>x>>y;
- 82: p[i] = Point(x,y);
- 83: }
- 84: for ( int i = 0; i < m; i++ ) {
- 85: long long x,y;
- 86: cin>>x>>y;
- 87: Point t(x,y);
- 88: for ( int j = 0; j < n; j++ ) {
- 89: Q.push(E(j,MAXSIZE+i,t.dis(p[j])));
- 90: }
- 91: }
- 92: }
- 93:
- 94: int DFS( int x ) {
- 95: for ( int i = head[x]; i != -1; i = e[i].next ) {
- 96: int y = e[i].y;
- 97: if ( !visited[y] ) {
- 98: visited[y] = 1;
- 99: if ( ( -1 == mark[y] ) || ( DFS(mark[y]) ) ) {
- 100: mark[y] = x;
- 101: return 1;
- 102: }
- 103: }
- 104: }
- 105: return 0;
- 106: }
- 107:
- 108: bool test() {
- 109: memset(mark,-1,sizeof(mark));
- 110: int result = 0;
- 111: for ( int i = 0; i < n; i++ ) {
- 112: memset(visited,0,sizeof(visited));
- 113: result += DFS(i);
- 114: }
- 115: if ( result == k ) {
- 116: return true;
- 117: } else {
- 118: return false;
- 119: }
- 120: }
- 121:
- 122: void solve () {
- 123: for ( int i = 0; i < k; i++ ) {
- 124: E ex = Q.top();
- 125: Q.pop();
- 126: add(ex);
- 127: last = ex.l;
- 128: }
- 129: while ( !test() ) {
- 130: E ex = Q.top();
- 131: Q.pop();
- 132: add(ex);
- 133: last = ex.l;
- 134: }
- 135: cout<<last<<endl;
- 136: }
- 137:
- 138: int main() {
- 139: input();
- 140: solve();
- 141: }
来更新一篇blog吧的更多相关文章
- 如何在一小时内更新100篇文章?-Evernote Sync插件介绍
上一篇"手把手教你制作微信小程序,开源.免费.快速搞定",已经教会你如何快速制作一个小程序,但作为资讯类小程序,内容不可少,并且还需要及时更新. 但是,如果让你复制粘贴,可能还需要 ...
- 一篇blog带你了解java中的锁
前言 最近在复习锁这一块,对java中的锁进行整理,本文介绍各种锁,希望给大家带来帮助. Java的锁 乐观锁 乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人 ...
- 第一篇blog
之前不用blog,但是在杭电oj,poj上刷题,总会自己总结题型和使用什么算法,算法模板,自己在笔记本上写,耗时费力,感觉用键盘敲得总结,分享,大家相互学习提高.有时遇到不会做的,或者总是在oj上跑的 ...
- 我的第一篇blog
加入博客园两年多了,学习.从事编程也两年多了,一直是在网上找资料,都没有认真写写博客. 博客园里面好多功能都还不会用,今天起我也要在博客园写自己的blog了.感觉很高大上的样纸!!
- 空格哥的第一篇Blog
首先十分感谢博客园在这里给我的平台,我在这里学习到了很多东西,响应的,我也想要在这里记录下自己的心路历程!在学习的过程中,希望博客园一直陪伴我,小弟在这里不胜感激!这是小弟的第一篇博客,很多东西都不是 ...
- 更新几篇之前写在公众号上的文章:线性可分时SVM理论推导;关联分析做捆绑销售和推荐;分词、去停用词和画词云
适合阅读人群:有一定的数学基础. 这几篇文章是16年写的,之前发布在个人公众号上,公众号现已弃用.回过头来再看这几篇文章,发现写的过于稚嫩,思考也不全面,这说明我又进步了,但还是作为学习笔记记在这里了 ...
- 我的第一篇blog—— 一起来赛马呀
作为一名大三的学生现在开始学习acm,或许太晚.感叹时光蹉跎....我的blog将以讲解的形式的发布,以专题的形式的形式介绍一些基本的知识和经典的题目.虽然感觉自己所剩时间无多,但也希望起到前人种 ...
- 人生的第一篇blog
开始写博客了,人生第一篇博客啊,要写些什么呢?想想也没有什么头绪,随便写写吧. 这学期要使用代码管理工具了,要写团队项目了.一直以来都是自己一个人在默默编程,没有过合作经历.对于代码的管理也只是一直在 ...
- EC2的维护更新-总结篇及有效经验分享
2014年10月11日 号,我们对不到10%的EC2实例的完毕了重新启动.来预防不论什么与Xen安全通报(XSA-108)相关的安全风险. 日之前都有义务遵守相关问题的保密要求.直到它被向公众公布. ...
随机推荐
- hibernate中一对多Set的排序问题
因为set是无序的,一旦涉及set排序,就需要配置hibernate的配置文件,参考如下博文 http://ykyfendou.iteye.com/blog/2094325
- JAVAAPI学习之Calendar类;Calendar类set()、add()、roll()方法区别
JAVAAPI学习之Calendar类 http://blog.csdn.net/myjlvzlp/article/details/8065775(写的很好,清晰易懂) Calendar类set(). ...
- 分享一张oracle scan图
- 注解 @RequestMapping
通过RequestMapping注解可以定义不同的处理器映射规则. 1.URL路径映射 @RequestMapping(value="/item")或@RequestMapping ...
- 嵌入式web server——Goahead移植要点
前言 在嵌入式设备中,在没有液晶显示的情况下,可以使用web来访问设备,查看设备的运行状态以及进行参数设置,类似于路由器设置.网上有很多关于各种web server的优劣的评论,在此不讨论,只是介绍其 ...
- SQLITE和QT
sqlite3数据库支持事务 例如: BEGIN DEFERRED TRANSACTION; INSERT INTO main.test_transaction (test_unique) VALUE ...
- Fizz Buzz
class Solution { public: /** * param n: As description. * return: A list of strings. */ vector<st ...
- [CSS]文本属性(Text)
CSS 文本属性(Text) 属性 描述 CSS color 设置文本的颜色. 1 direction 规定文本的方向 / 书写方向. 2 letter-spacing 设置字符间距. 1 lin ...
- Lsp修复
打开电脑,进入命令提示符窗口,快捷键win+r. 在窗口中输入“cmd”进入命令符窗口. 在窗口中输入:输入netsh winsock reset,然后按下回车键. 然后稍等片刻, ...
- python 元组问题解决
a = (1,2,{'k1':'b2'}) a[2]['k1'] = 5 print(a) (1, 2, {'k1': 5}) 为什么元素'b2' = 5 应该是元素'k1' = 5 求解 a[2][ ...