您的位置:首页 > 其它

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");
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: