保留道路
来源:互联网 发布:汉聚网络怎么样 编辑:程序博客网 时间:2024/05/01 08:20
50%的做法:
先按照s升序排序。
从小到大枚举maxg,把g小于maxg的边全部选出来,(因为前面已经排过序了),造一棵最小生成树,更新答案。时间复杂度≈O(m*m)。
100分的做法:
按照g升序排序。
维护一个n-1条边的边集,是上一个建造的最小生成树的边集。
从前往后枚举maxg,把这条边按照s用插入排序插入到当前n-1条边的集合中。
在这样的n条边的集合中建造一颗最小生成树,最后再把用到的边存到边集中(就是将没用到的删去),从而维护了一个n-1的边集。
刚才所说的边集其实就是维护的一棵最小生成树。
时间复杂度≈O(m*n)。
因为最小生成树的性质:在当前的最小生成树中插入一条边,构成了环,把环中最长的边删去就是新的最小生成树。
60分代码:
#include<iostream>#include<cstring>#include<algorithm>#include<vector>#include<cstdio>#include<map>#define LL long long#define N 50009using namespace std;int n,m,f[509];LL Ws,Wg,ans=(1ll*1<<62),order[N];struct H{int u,v;LL s,g;}b[N];LL maxg,maxs,num;bool cmp(H x,H y) { return x.s<y.s;}void init(){ for(int i=1;i<=n;i++) f[i]=i;}int find(int x) { if(x==f[x])return x; return f[x]=find(f[x]);} int main(){ scanf("%d%d%lld%lld",&n,&m,&Wg,&Ws); for(int i=1;i<=m;i++) { scanf("%d%d%lld%lld",&b[i].u,&b[i].v,&b[i].g,&b[i].s); b[i].s*=Ws;b[i].g*=Wg;order[i]=b[i].g; } sort(order+1,order+m+1); sort(b+1,b+m+1,cmp); for(int i=n-1;i<=m;i++) { init(); maxg=order[i];num=n; for(int j=1;j<=m;j++) if(b[j].g<=maxg) { int fx=find(b[j].u),fy=find(b[j].v); if(fx!=fy) { num--; f[fx]=fy; maxs=b[j].s; } if(num==1) break; } if(num==1) ans=min(ans,maxs+maxg); } if(ans==(1ll*1<<62))printf("-1\n"); else printf("%lld",ans); return 0;}
100分做法:
#include<iostream>#include<cstring>#include<algorithm>#include<vector>#include<cstdio>#include<map>#define LL long long#define N 50009using namespace std;int n,m,f[509],cnt,num;LL ans=(1ll*1<<62);LL Ws,Wg,order[N],r;struct H{ int u,v; LL s,g;}b[N],q[N],tree[N];bool used[N];LL maxg,maxs;bool cmp(H x,H y){ return x.g<y.g;} int find(int x) { if(x==f[x])return x; return f[x]=find(f[x]);} void get_ans(LL G){ maxg=G;maxs=0;num=n; for(int i=1;i<=n;i++) f[i]=i; for(int i=1;i<=cnt;i++) q[i]=tree[i],used[i]=0; for(int i=1;i<=cnt;i++) { int fx=find(q[i].u),fy=find(q[i].v); if(fx!=fy) { maxs=max(maxs,q[i].s); f[fx]=fy; num--; used[i]=1; } } if(num==1) { int p=0; ans=min(ans,maxs+maxg); for(int i=1;i<=cnt;i++) { if(used[i]) tree[++p]=q[i]; } cnt=p; }}int main(){ scanf("%d%d%lld%lld",&n,&m,&Wg,&Ws); for(int i=1;i<=m;i++) { scanf("%d%d%lld%lld",&b[i].u,&b[i].v,&b[i].g,&b[i].s); b[i].g*=Wg;b[i].s*=Ws; } sort(b+1,b+m+1,cmp); for(int i=1;i<=m;i++) { if(b[i].g+b[i].s>ans) continue;//这个剪枝可以减少很多多余的计算 int pos=cnt+1; for(int j=1;j<=cnt;j++) if(tree[j].s>b[i].s) { pos=j;break; } if(pos==cnt+1) tree[++cnt]=b[i]; else { ++cnt; for(int j=cnt;j>pos;j--) tree[j]=tree[j-1]; tree[pos]=b[i]; } if(cnt<n-1) continue; get_ans(b[i].g); } if(ans==(1ll*1<<62)) printf("-1"); else printf("%lld",ans); return 0;}
阅读全文
1 0
- 保留道路
- 保留道路
- 保留道路
- 保留道路 Road
- C++——NOIP模拟题——保留道路
- JZOJ100042. 【NOIP2017提高A组模拟7.12】保留道路
- 道路
- 道路
- 道路
- 保留
- 保留
- 保留
- 保留
- 硬件道路: 软件道路:
- 成功道路
- 人生道路!!!
- 道路重建
- 道路网络
- 欢迎使用CSDN-markdown编辑器
- matplotlib 中文问题 及常见api
- 3130: [Sdoi2013]费用流
- 微信支付中遇到的问题
- Eclipse 使用jdk9不能打开
- 保留道路
- iOS9获取当前系统语言编码
- extjs和fros框架前台请求,后台通过list集合接收
- 设计模式学习
- C++ cout格式化输出
- 经常使用的几种判断手机端或PC端的方法
- MySQL基本命令梳理--小白专用
- KazaQ's Socks
- LightOJ