[BZOJ1050] [HAOI2006] 旅行comf (Kruskal, LCT)
Description
给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000)。给你两个顶点S和T
,求一条路径,使得路径上最大边和最小边的比值最小。如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出
这个比值,如果需要,表示成一个既约分数。 备注: 两个顶点之间可能有多条路径。
Input
第一行包含两个正整数,N和M。下来的M行每行包含三个正整数:x,y和v。表示景点x到景点y之间有一条双向
公路,车辆必须以速度v在该公路上行驶。最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速
度比最小的路径。s和t不可能相同。
1<N<=500,1<=x,y<=N,0<v<30000,0<M<=5000,可能出现自环
Output
如果景点s到景点t没有路径,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。如果需要,输出一
个既约分数。
Sample Input
4 2
1 2 1
3 4 2
1 4
3 3
1 2 10
1 2 5
2 3 8
1 3
3 2
1 2 2
2 3 4
1 3
Sample Output
IMPOSSIBLE
5/4
2
HINT
Source
Solution
首先把边按边权排序
第一种方法:枚举第一条边是哪条,之后从这条边开始做$Kruskal$,直到$S$与$T$联通或所有边都用完
因为最小生成树可以保证最大边权尽量小,所以在最小边权指定的情况下可以找到比值最小的情况,复杂度$O(m^2)$
($Kruskal$不好玩,我们来玩$LCT$吧)
第二种方法:我们用$LCT$维护最小生成树,按顺序插入边,当新插入的边的两端已经在树上时,把边权最小的边断开,再把这条边插进去
联通性什么的都挺好判断的不用我多说了吧,复杂度是$O(mlog^2n)$的
(好像有一些细节没讲,算了不管啦)
1 #include <bits/stdc++.h> 2 using namespace std; 3 struct edge 4 { 5 int u, v, w; 6 bool operator< (const edge &rhs) const 7 { 8 return w < rhs.w; 9 } 10 }e[5555]; 11 struct LCT 12 { 13 int c[2], fa, rev, val, mn, mx; 14 int& operator[] (int x) 15 { 16 return c[x]; 17 } 18 }a[5555]; 19 int sta[5555], top; 20 21 int gcd(int x, int y) 22 { 23 return y ? gcd(y, x % y) : x; 24 } 25 26 void push_up(int k) 27 { 28 int c0 = a[k][0], c1 = a[k][1]; 29 a[k].mn = a[k].val ? k : 0, a[k].mx = k; 30 if(a[a[c0].mn].val && a[a[c0].mn].val < a[a[k].mn].val) 31 a[k].mn = a[c0].mn; 32 if(a[a[c0].mx].val > a[a[k].mx].val) a[k].mx = a[c0].mx; 33 if(a[a[c1].mn].val && a[a[c1].mn].val < a[a[k].mn].val) 34 a[k].mn = a[c1].mn; 35 if(a[a[c1].mx].val > a[a[k].mx].val) a[k].mx = a[c1].mx; 36 } 37 38 void push_down(int k) 39 { 40 if(a[k].rev) 41 { 42 swap(a[k][0], a[k][1]), a[k].rev = 0; 43 a[a[k][0]].rev ^= 1, a[a[k][1]].rev ^= 1; 44 } 45 } 46 47 bool isroot(int x) 48 { 49 return a[a[x].fa][0] != x && a[a[x].fa][1] != x; 50 } 51 52 void rotate(int x) 53 { 54 int y = a[x].fa, z = a[y].fa, dy = a[y][1] == x; 55 if(!isroot(y)) a[z][a[z][1] == y] = x; 56 a[y][dy] = a[x][!dy], a[a[x][!dy]].fa = y; 57 a[x][!dy] = y, a[y].fa = x, a[x].fa = z; 58 push_up(y); 59 } 60 61 void splay(int x) 62 { 63 sta[top = 1] = x; 64 for(int i = x; !isroot(i); i = a[i].fa) 65 sta[++top] = a[i].fa; 66 while(top) 67 push_down(sta[top--]); 68 while(!isroot(x)) 69 { 70 int y = a[x].fa, z = a[y].fa; 71 if(!isroot(y)) 72 if(a[y][1] == x ^ a[z][1] == y) rotate(x); 73 else rotate(y); 74 rotate(x); 75 } 76 push_up(x); 77 } 78 79 void access(int x) 80 { 81 for(int i = 0; x; x = a[x].fa) 82 splay(x), a[x][1] = i, i = x; 83 } 84 85 void make_root(int x) 86 { 87 access(x), splay(x), a[x].rev ^= 1; 88 } 89 90 void link(int x, int y) 91 { 92 make_root(x), a[x].fa = y; 93 } 94 95 void cut(int x, int y) 96 { 97 make_root(x), access(y), splay(y); 98 a[y][0] = a[x].fa = 0, push_up(y); 99 } 100 101 int find_root(int x) 102 { 103 access(x), splay(x); 104 while(a[x][0]) 105 x = a[x][0]; 106 return x; 107 } 108 109 int main() 110 { 111 int n, m, u, v, sss, ttt, mx = 50000, mn = 1, tmp; 112 scanf("%d%d", &n, &m); 113 for(int i = 1; i <= m; ++i) 114 { 115 scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w); 116 if(e[i].u == e[i].v) --i, --m; 117 } 118 scanf("%d%d", &sss, &ttt); 119 sss += m, ttt += m; 120 sort(e + 1, e + m + 1); 121 a[0].val = 50000, a[0].mx = 5554; 122 for(int i = 1; i <= m + n; ++i) 123 a[i].val = e[i].w, push_up(i); 124 for(int i = 1; i <= m; ++i) 125 { 126 u = e[i].u + m, v = e[i].v + m; 127 if(find_root(u) == find_root(v)) 128 { 129 make_root(u), access(v), splay(v); 130 tmp = a[v].mn; 131 cut(e[tmp].u + m, tmp); 132 cut(e[tmp].v + m, tmp); 133 } 134 link(u, i), link(v, i); 135 if(find_root(sss) != find_root(ttt)) continue; 136 make_root(sss), access(ttt), splay(ttt); 137 if(1.0 * a[a[ttt].mx].val / a[a[ttt].mn].val < 1.0 * mx / mn) 138 mx = a[a[ttt].mx].val, mn = a[a[ttt].mn].val; 139 } 140 tmp = gcd(mx, mn), mx /= tmp, mn /= tmp; 141 if(mx == 50000) puts("IMPOSSIBLE"); 142 else if(mn == 1) printf("%d\n", mx); 143 else printf("%d/%d\n", mx, mn); 144 return 0; 145 }
View Code
转载于:https://www.cnblogs.com/CtrlCV/p/5667745.html
[BZOJ1050] [HAOI2006] 旅行comf (Kruskal, LCT)相关推荐
- [bzoj1050 HAOI2006] 旅行comf (kruskal)
传送门 Description 给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000).给你两个顶点S和T,求 一条路径,使得 ...
- bzoj1050: [HAOI2006]旅行comf
题面在这里 题意: 给一个图,每条边有边权. 给一个s和t,如果s和t之间没有路径输出IMPOSSIBLE,否则输出路径上最大边和最小边的比值的最小值. 做法: 你把边从小到大排序.那么对于一个最小值 ...
- BZOJ1050 [HAOI2006]旅行comf(Kruskal算法)
SPFA是错误的:局部最优不能保证全局最优,因为要求的是比例最小,与路的长短无直接关系 可以设计m^2的算法: 先将边按长度排序,然后每次枚举最小边的长度w[i]作限定,依次加入更大的边, 当加到某条 ...
- bzoj1050 [HAOI2006]旅行comf
题目 枚举最小边,在用kruskal方法来让S与T,联通,这样比值就最优了.. #include<bits/stdc++.h> using namespace std; int f[501 ...
- BZOJ1050 HAOI2006 旅行comf 生成树+枚举
题意:给订一张无向图,求一条S到T的路径,使得路径上的最大边权与最小边权的比值最小 题解:将边由小到大排序,暴力枚举最小边,然后借鉴Kruskal的思想,由小到大加入每一条大于初始边的边,检验S与T是 ...
- BZOJ1050 [HAOI2006]旅行comf
题目描述: 给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000).给你两个顶点S和T,求 一条路径,使得路径上最大边和最小边 ...
- bzoj1050 [HAOI2006]旅行comf(并查集)
要求路径上最大边与最小边比值的最小值.我们知道,如果固定最小值,最大值越接近最小值,他们的比值越小.因此我们可以采用类似bzoj3454的方法,把所有边从小到大排序,枚举最小值,再枚举最大值,用并查集 ...
- BZOJ1050 [HAOI2006]旅行comf (并查集)
题意分析 一开始想用最短路的方法维护,然后更新信息.失败了. 想了半天,发现跟lrj书上面的一道题很像,看边才5000,暴力可做. 对边排序后枚举sta,直到发现起点和重点在一个联通块里面,统计答案即 ...
- 【bzoj1050】[HAOI2006]旅行comf
1050: [HAOI2006]旅行comf Time Limit: 10 Sec Memory Limit: 162 MB Submit: 2813 Solved: 1534 [Submit][ ...
最新文章
- 利用python获取指定url在ATS中缓存对象的信息
- 在idea项目中的android包不能识别_项目调试编译和部署运行
- 通用数据级别权限的框架设计与实现(4)-单条记录的权限控制
- VC代码的编写和调试---编写易于调试的VC代码
- 全球无人车头部三强格局明确,百度自动驾驶估值400亿美金
- python 之pulp 线性规划介绍及举例
- 天联高级版客户端_天联客户端登录的KIS旗舰版打印单据问题
- Notepadd ++ PluginManager安装
- 前端每日实战:164# 视频演示如何用原生 JS 创作一个数独训练小游戏(内含 4 个视频)...
- skill alpha protocol
- Android中集成Jpush实现推送消息通知与根据别名指定推送附示例代码下载
- Linux必知必会的基本命令和部署项目流程
- Oracle命令--如何查看oracle中创建的所有目录
- 删除字符,用外部函数
- Robot Framework 自动化框架大纲
- 梦幻西游的脚本怎么制作
- ValueError: operands could not be broadcast together with shapes (416,416,4) (3,)
- PAT A 1013. Battle Over Cities
- Android Camera高级特性——手动对焦
- does not exist or is not a readable directory
热门文章
- python 多线程内子线程结束后执行主线程
- 微信oa服务器,微信oa系统是什么?微信如何与oa系统进行结合?
- 传奇引擎注册服务器,GeeM2引擎架设传奇不能注册账号 进不去游戏
- word2016 上次启动时失败以安全模式能够解决该问题【office专业版】
- 4k纸是几厘米乘几厘米_4k纸有多大长多少宽多少
- 跟王佩丰学习VBA-纯代码(1-8讲)
- 2022-2028年中国尘螨脱敏治疗药物行业市场运行态势及发展战略研究报告
- hypermill后处理构造器安装_铁道车辆不可缺少的部件——远心集尘器
- php guzzle并发,使用Guzzle并发请求接口
- ERROR CoarseGrainedExecutorBackend: RECEIVED SIGNAL TERM