贪心,暴力,网络流,匹配(MZL's City,HDU 5352)
来源:互联网 发布:程序员常用工具 知乎 编辑:程序博客网 时间:2024/06/07 14:17
这个题目可以抽象成以下问题。
有一个M层的架子,每层最多放K颗珍珠,你有N个不同的珍珠,每颗珍珠都只能放在某些特定的层里,问怎么安排放置的方案,使得珍珠尽量往下层放(尽量往下层放的概念很模糊,准确一点讲就是字典序最小)。
思考之后觉得这是一个很动态的问题,考虑过动态规划,但是感觉不怎么好定义状态,更别提状态转移了。然后就考虑转贪心,思考了很多办法,最后想到了一个暴力的方法,能保证正确性,但是时间复杂度不是很好估计(最坏情况铁定超时,但是感觉这个上界非常松),所以决定试一下,然后就过了,而且时间还比常规解法快很多。
具体解法就是类似模拟,先把所有珍珠放在最顶层(最顶层是一个虚层,代表无限高的层)。然后按照从上到下的顺序遍历每个层的每个珍珠,然后尝试把它往下放。
如果下层还有多余空间,我们就直接往下放。
否则我们就要考虑将另一颗珍珠“置换”上去。
A把B“置换”上去的意思就是,将A放到B的位置,然后把B放到一个更高但是又比A原来的位置更低的位置。
这样的解法能够保证正确性,但是时间复杂度很不好估计,最坏情况下就是O(M*N*M*N*M*logN),肯定超时的,而且还没有考虑set的常数。但是能明显感到这个上界是非常松的,自己大致估计了一下平均情况,感觉搞不好真的可以过,所以就试了一下,然后就过了。
关于正确性,因为我们是从上往下遍历,能优化就优化,实在优化不了才跳过。因此当算法结束以后,我们无法再通过任何变动使得答案更优了。
关于其它解法,看了网上的解法,学习了一下,自己没有亲自实现,但还是想写一写理解。
主要看了这篇博客:http://blog.csdn.net/fipped/article/details/47305699
1、最小费用最大流
这个是最好理解的方法,但其他方法其实也就是这个方法的特例。
建立N个点代表城市,建立M个点代表年份。
建立一个超级汇点,所有城市都连一条容量为1,费用为0的边到汇点。
建立一个超级源点,对每个年份都连一条容量为K的边,费用为M+1-年份。
每个年份都对可以建造的城市连一条容量为1,费用为0的边。
然后跑最小费用最大流,得到的最大流就是最多的城市数。
考虑每一个年份节点即可知道对应年份所建立的城市数。
为什么源点与年份之间的边花费为M+1-年份呢?
主要原因是因为这个是最大流下的最小费,而不是单纯的最小费。
如果是单纯的最小费,这个花费的设置可能会导致问题,应该设成210^(M+1-年份)才合理,只有设成这个值才能代表前一年的无穷大。
但是由于满足最大流的限制,因此备选的方案的流量应该都是相等的,在这种情况下只需要设成M+1-年份就一定可以通过求最小费得出最优解。
2、最大流
没有使用最小费,只是单纯的多次跑最大流。
讲的更具体一点:
建立N个点代表城市。
建立一个超级汇点,所有城市都连一条容量为1的边到汇点。
然后逐年地动态建图,并跑一次最大流。
即按降序考虑每一个年份,对于一个特定的年份,新建一个节点代表当年,并对所有可以建立的城市都连一条容量为1的边。
然后从源点连一条容量为K的边到当年的节点,然后跑一次最大流。
每年新增的流量就是当年建造的城市量,加起来就是总城市量。
为什么这个算法是正确的呢?
我们在紫书P371上可以看到关于最小费用流的一句话。
只要初始流是该流量下的最小费用可行流,每次增广后的新流都是新流量下的最小费用流。
最小费用最大流的算法就是基于这句话来实现的,Edmonds-Karp算法就是每次沿着最短路进行增广,多次增广直到无法再增加流量,因此算法结束后得到的最大流一定是最小费的。
本题的最大流解法其实本质上也就是最小费用最大流解法。
按照降序考虑每一个年份跑最大流,其实就等价于每次沿着最短路进行增广,因此最后得到的结果也就是正确的了。
3、匹配
我们都知道,最大流可以解决匹配问题,但匹配问题不一定能解决最大流问题。
但在本题中,我们可以用匹配来代替最大流,同样可以得到答案。
代替的方式就是将一个年份拆成K个点,然后跑匈牙利算法,这同时也是解决多重匹配问题的一个办法。
其他细节和思路可以参考2。
关于多重匹配:http://blog.csdn.net/allenjy123/article/details/6674118
上面三种方法都没有亲自实现,可能思路或理解会有错误,仅供参考。
贪心暴力的代码
#include<stdio.h>#include<set>#include<string.h>#include<vector>#include<algorithm>using namespace std;const int maxn = 210;const int maxc = 510;int N,M,K;set<int>G[maxn];set<int>ceng[maxc];vector<int>vec[maxn];int vis[maxn];int cntceng;void init(){ scanf("%d %d %d",&N,&M,&K); ceng[0].clear(); for(int i=1;i<=N;i++) ceng[0].insert(i),G[i].clear(),vec[i].clear(); cntceng=1;}void dfs(int u){ vis[u]=1; vec[u].push_back(cntceng-1); for(set<int>::iterator it = G[u].begin();it!=G[u].end();++it) { int v = *it; if(!vis[v]) dfs(v); }}void build(){ int op,u,v,p; for(int i=1;i<=M;i++) { scanf("%d",&op); if(op==2) { scanf("%d %d",&u,&v); G[u].insert(v); G[v].insert(u); } else if(op==3) { scanf("%d",&p); for(int j=1;j<=p;j++) { scanf("%d %d",&u,&v); G[u].erase(v); G[v].erase(u); } } else { scanf("%d",&p); memset(vis,0,sizeof(vis)); ceng[cntceng++].clear(); dfs(p); } }}void solve(){ init(); build(); for(int i=0;i<cntceng;i++) { for(set<int>::iterator it = ceng[i].begin();it!=ceng[i].end();) { bool ok = false; for(int j=(int)vec[*it].size()-1;j>=0&&vec[*it][j]>i;j--) { int CENG = vec[*it][j]; if((int)ceng[CENG].size()<K) { ok=true; ceng[CENG].insert(*it); ceng[i].erase(*it++); break; } for(set<int>::iterator it2 = ceng[CENG].begin();it2!=ceng[CENG].end();++it2) { if(*it2!=*it) for(int k = (int)vec[*it2].size()-1;k>=0&&vec[*it2][k]>i;--k) { //printf("%d\n",vec[*it2][k]); //printf("%d\n",ceng[vec[*it2][k]].size()); if(vec[*it2][k]<CENG&&(int)ceng[vec[*it2][k]].size()<K) { ok=true; ceng[vec[*it2][k]].insert(*it2); ceng[CENG].erase(*it2); ceng[CENG].insert(*it); ceng[i].erase(*it++); break; } } if(ok) break; } if(ok) break; } if(!ok) ++it; } } printf("%d\n",N-ceng[0].size()); for(int i=1;i<cntceng;i++) printf("%d%c",ceng[i].size(),i+1==cntceng?'\n':' ');}int main(){ int T; scanf("%d",&T); while(T--) solve(); return 0;}
- 贪心,暴力,网络流,匹配(MZL's City,HDU 5352)
- HDU 5352 MZL's City(网络流)
- HDU 5352 - MZL's City(网络流‘最小费用流)
- HDU 5352(MZL's City-费用流)
- hdu 5352 MZL's City (最大流 || 费用流)
- Hdu 5352 MZL's City (最小费用最大流)
- HDU 5352 MZL's City
- MZL's City(网络流)
- MZL's City (hdu 5352 最小费用流 ||二分图匹配)
- HDOJ 5352 MZL's City 匈牙利匹配
- hdu 5352 MZL's City 【二分图】
- HDU 5352 MZL's City(2015 多校 第5场,最小费用最大流)
- HDU 5352 MZL's City(最小费用最大流-mcmf)
- 【费用流】 HDOJ 5352 MZL's City
- HDU 5352 MZL's City(最小费用最大流)经典 2015 Multi-University Training Contest 5
- hdu 5352 MZL's City 2015多校联合训练赛#5 费用流
- hdu5352 MZL's City(最小费用最大流问题)
- hdu5352 MZL's City 网络流,最小费用最大流模板
- 关于Mybatis的$和#,你真的知道他们的细节吗?
- 设计模式之策略模式
- mybatis环境搭建(一)
- HDU
- seckill
- 贪心,暴力,网络流,匹配(MZL's City,HDU 5352)
- jetty9 websocket发送消息死锁,引发内存溢出
- Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks
- Java读取txt文件和写入txt文件
- 什么是SCM?
- 我所理解的面向对象
- [SourceInsight]打开当前文件目录
- 漫谈操作系统7 -- 一切皆为文件
- Android_实现水滴效果