hdu 1598 find the most comfortable road (并查集+枚举下界)
2015-09-20 09:16
417 查看
find the most comfortable road
题目链接:Problem - 1598题目大意:求一条差值最小的路。
题目分析:
思路一:深搜,一一枚举各条合法的路,如果此路连接了起始点和结束点,计算此时的差,然后比较得出差得最小值。
(路的个数有1000条,此方法肯定会超时)
思路二:dijkstra,找出一条最短路,一路上记录最大值,最小值,比如1->2->5,记录Low[5][2].maxs,和low[5][2].mins(5是pos,2是pre)最后对low[e][]扫一遍,得出最小值。(此方法只能保留一个前驱的mins,maxs,比如2 -> 5有[mins,maxs]=[2,5]和[1,4],2个范围不冲突,应全部保留,此方法值能保留一个,wa)
思路三:并查集+枚举下界。对路的长度进行排序,枚举下界mins,进行并查集操作,因为每次枚举都是先选小边再选大边,所以一旦满足finds(end)=finds(start),所得到的差值一定是此下界最小的情况。
思路分析:
1)存路并排序(road[1005])
2)枚举下界,mins值,每次都进行并查集操作,当start和end点根相同时记录cha,比较出所有情况下cha的最小值。
笔者心得:做图论题一是考虑方法,而是考虑复杂度,否则一直会死在错误算法里,笔者就再思路二上挣扎了1天。
贴AC代码:
#include <stdio.h> //定义输入/输出函数 #include <limits.h> //定义各种数据类型最值常量 #include <math.h> //定义数学函数 #include <stdlib.h> //定义杂项函数及内存分配函数 #include <string.h> //字符串处理 #include <algorithm>//算法 #include <queue>//队列 #include <stack>//栈 #include <vector> using namespace std; int n, m, q, mins, maxs, ans, s, e; int re[205]; struct node{ int from, to, cost; }; node road[1005]; int finds(int x){ if (re[x] == x) return x; else return re[x] = finds(re[x]); } int cmp(node a, node b){ return a.cost < b.cost; } int main() { while (scanf("%d", &n) != EOF && n){ scanf("%d", &m); for (int i = 0; i < m; i++){ scanf("%d%d%d", &road[i].from, &road[i].to, &road[i].cost); } sort(road, road + m, cmp); scanf("%d", &q); while (q--){ scanf("%d%d", &s, &e); ans = 1000005; int flag = 0; for (int i = 0; i < m; i++){ //枚举min; mins = 1000005; maxs = 0; for (int j = 1; j <= n; j++) re[j] = j; for (int j = i; j < m; j++){ //kruskal if (finds(road[j].from) == finds(road[j].to)) continue; re[finds(road[j].from)] = finds(road[j].to); mins = min(road[j].cost, mins); maxs = max(road[j].cost, maxs); //printf("%d <-> %d == [%d, %d]\n", road[j].from, road[j].to, mins, maxs); if (finds(s) == finds(e)){ flag = 1; if (ans > maxs - mins) ans = maxs - mins; break; } } } if (flag == 1) printf("%d\n", ans); else printf("-1\n"); } } }
贴思路二代码:
#include <stdio.h> //定义输入/输出函数 #include <limits.h> //定义各种数据类型最值常量 #include <math.h> //定义数学函数 #include <stdlib.h> //定义杂项函数及内存分配函数 #include <string.h> //字符串处理 #include <algorithm>//算法 #include <queue>//队列 #include <stack>//栈 #include <vector> using namespace std; int n, m, Q, s, e, tmp; int map[205][205]; struct node{ int mins, maxs, cha; }; node low[205]; bool vis[205]; void input() { int a, b, c; scanf("%d%d%d", &a, &b, &c); map[a][b] = c; map[b][a] = c; } void dijkstra() { memset(low, 0, sizeof(low)); for (int i = 0; i < 205; i++) low[i].cha = 1000005; memset(vis, 0, sizeof(vis)); //int flag = 1; for (int i = 1; i <= n; i ++){ if (map[s][i] == 0) continue; low[i].mins = low[i].maxs = map[s][i]; low[i].cha = 0; // flag = 0; } //从s出发,初始化 //if (flag == 1) return; // 是否连通 vis[s] = 1; for (int i = 0; i < n-1;i ++){ unsigned int cmp = 1000005; tmp = 0; for (int j = 1; j <= n; j++){ if (low[j].cha < cmp && vis[j] == 0){ cmp = low[j].cha; tmp = j; } } if (tmp == 0) continue; vis[tmp] = 1; for (int j = 1; j <= n; j++){ if (vis[j] == 1) continue; if (map[tmp][j] == 0) continue; int k = max(low[tmp].maxs, map[tmp][j]); int kk = min(low[tmp].mins, map[tmp][j]); if (low[j].cha > k - kk){ low[j].cha = k - kk; low[j].maxs = k; low[j].mins = kk; } //printf("%d(%d,%d) --> %d == %d\n", tmp,low[j].maxs, low[j].mins, j, low[j].cha); } } } int main() { while (scanf("%d", &n) != EOF && n){ scanf("%d", &m); memset(map, 0, sizeof(map)); for (int i = 0; i < m; i ++) input(); scanf("%d", &Q); while (Q--){ scanf("%d%d", &s, &e); dijkstra(); if (low[e].cha != 1000005)printf("%d\n", low[e].cha); else printf("-1\n"); } } }
贴思路一代码:
#include <stdio.h> //定义输入/输出函数 #include <limits.h> //定义各种数据类型最值常量 #include <math.h> //定义数学函数 #include <stdlib.h> //定义杂项函数及内存分配函数 #include <string.h> //字符串处理 #include <algorithm>//算法 #include <queue>//队列 #include <stack>//栈 #include <vector> using namespace std; int n, m, q, mins, maxs, s, e, couts, ans; bool vis[205]; int map[205][205]; int road[205]; void dfs(int loc) { if (loc == e){ maxs = 0; mins = 1000005; for (int j = 0; j < couts; j++){ if (road[j] > maxs) maxs = road[j]; if (road[j] < mins) mins = road[j]; } if (ans > maxs - mins) ans = maxs - mins; return; } for (int i = 1; i <= n; i++){ if (vis[i] == 1) continue; if (map[loc][i] == 0) continue; road[couts++] = map[loc][i]; vis[i] = 1; dfs(i); vis[i] = 0; couts--; } } int main() { while(scanf("%d", &n) != EOF && n){ scanf("%d", &m); memset(map, 0, sizeof(map)); while(m--){ int a, b, c; scanf("%d%d%d", &a, &b, &c); map[a][b] = map[b][a] = c; } scanf("%d", &q); while (q--){ scanf("%d%d", &s, &e); memset(vis, 0, sizeof(vis)); memset(road, 0, sizeof(road)); couts = 0; vis[s] = 1; ans = 1000005; if (s == e){ printf("0\n"); continue; } dfs(s); if (ans != 1000005) printf("%d\n", ans); else printf("-1\n"); } } }
相关文章推荐
- Python 读取Json的方法
- Android 简单的智能机器人聊天软件
- 黑马程序员——反射
- java final 关键字
- 螺旋方阵
- spring jdbcTemplate
- 如何搭建个人博客
- 基于XBee进行ZigBee组网(一)——XBee介绍
- 杭电1002
- 去掉隐藏字符解决办法
- 模板类MyArry
- java中的 核心概念
- [CareerCup] 9.5 Permutations 全排列
- 使用FileReader类、BufferedReader类、FileInputStream类三种方式进行文件的读取
- 【FPGA】FPGA错误汇总 ( 不断更新... )
- vb.net窗口继承(房重建知识汇总)
- JSON 解析 + listView + AsyncTask 的结合使用做个菜谱应用(总结)
- Android ListView的中的数据更新时遇到的一些问题的总结
- Object-C学习笔记
- 进制转换