UVa 10816 - Travel in Desert

题目:穿越沙漠有几个区域,每个区域间有路径链接(两点间路径不唯一);

            寻找一条路径使得,路径中的最高温度最小(存在多组取距离最小)。

分析:图论、最短路、最小生成树。分两步求解。

            首先,寻找到最小的最高温度,這裡使用dijkstra算法;

            然後,利用上述最高溫度作為選取路徑的閾值,求最短路,使用dijkstra算法。

说明:第888題╮(╯▽╰)╭。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const int oo = 100000000;

// link_begin
typedef struct _link
{
	int    point;
	double R;
	double D;
	_link* next;
}link;
link* link_head[101];
link  link_node[20002];
int   link_size;

void link_initial()
{
	link_size = 0;
	memset(link_head, 0, sizeof(link_head));
	memset(link_node, 0, sizeof(link_node));
}

void link_add_edge(int u, int v, double r, double d)
{
	link_node[link_size].point = v;
	link_node[link_size].R = r;
	link_node[link_size].D = d;
	link_node[link_size].next = link_head[u];
	link_head[u] = &link_node[link_size ++];
}
// link_end

double dist[101];
double temp[101];
int    next[101];
int    used[101];

double max(double x, double y)
{
	return x>y?x:y;
}

int main()
{
	int    N, E, S, T, X, Y;
	double R, D;
	while (~scanf("%d%d%d%d",&N,&E,&S,&T)) {
		for (int i = 1; i <= N; ++ i) {
			dist[i] = oo;
			temp[i] = oo;
			next[i] = i;
			used[i] = 0;
		}
		link_initial();
		for (int i = 1; i <= E; ++ i) {
			scanf("%d%d%lf%lf",&X,&Y,&R,&D);
			link_add_edge(X, Y, R, D);
			link_add_edge(Y, X, R, D);
		}
		
		int now = T;
		temp[now] = 0;
		used[now] = 1;
		for (int i = 2; i <= N; ++ i) {
			for (link* p = link_head[now]; p; p = p->next) {
				if (temp[p->point] > max(temp[now], p->R)) {
					temp[p->point] = max(temp[now], p->R);
				}
			}
			double min = oo;
			for (int i = 1; i <= N; ++ i) {
				if (!used[i] && min > temp[i]) {
					now = i;
					min = temp[i];
				}
			}
			used[now] = 1;
		}
		
		for (int i = 1; i <= N; ++ i) {
			used[i] = 0;	
		}
		now = T;
		dist[now] = 0;
		used[now] = 1;
		for (int i = 2; i <= N; ++ i) {
			for (link* p = link_head[now]; p; p = p->next) {
				if (dist[p->point] > dist[now] + p->D && p->R <= temp[S]) {
					dist[p->point] = dist[now] + p->D;
					next[p->point] = now;
				}
			}
			double min = oo;
			for (int i = 1; i <= N; ++ i) {
				if (!used[i] && min > dist[i]) {
					now = i;
					min = dist[i];
				}
			}
			used[now] = 1;
		}
		
		int New = S;
		printf("%d",S);
		while (New != T) {
			printf(" %d",next[New]);
			New = next[New];
		}
		printf("\n%.1lf %.1lf\n",dist[S],temp[S]);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值