uva 10816 Travel in Desert (最小生成树 + 最短路)

来源:互联网 发布:excel数据标签连线 编辑:程序博客网 时间:2024/06/06 02:54

uva 10816 Travel in Desert

Description

There is a group of adventurers who like to travel in the desert. Everyone knows travelling in desert can be very dangerous. That’s why they plan their trip carefully every time. There are a lot of factors to consider before they make their final decision.

One of the most important factors is the weather. It is undesirable to travel under extremely high temperature. They always try to avoid going to the hottest place. However, it is unavoidable sometimes as it might be on the only way to the destination. To decide where to go, they will pick a route that the highest temperature is minimized. If more than one route satisfy this criterion, they will choose the shortest one.

There are several oases in the desert where they can take a rest. That means they are travelling from oasis to oasis before reaching the destination. They know the lengths and the temperatures of the paths between oases. You are to write a program and plan the route for them.

Input

Input consists of several test cases. Your program must process all of them.

The first line contains two integers N and E (1 ≤ N ≤ 100; 1 ≤ E ≤ 10000) where N represents the number of oasis and E represents the number of paths between them. Next line contains two distinct integers S and T (1 ≤ S, T ≤ N) representing the starting point and the destination respectively. The following E lines are the information the group gathered. Each line contains 2 integers X, Y and 2 real numbers R and D (1 ≤ X, Y ≤ N; 20 ≤ R ≤ 50; 0 < D ≤ 40). It means there is a path between X and Y, with length D km and highest temperature R oC. Each real number has exactly one digit after the decimal point. There might be more than one path between a pair of oases.

Output

Print two lines for each test case. The first line should give the route you find, and the second should contain its length and maximum temperature.

Sample Input

6 9
1 6
1 2 37.1 10.2
2 3 40.5 20.7
3 4 42.8 19.0
3 1 38.3 15.8
4 5 39.7 11.1
6 3 36.0 22.5
5 6 43.9 10.2
2 6 44.2 15.2
4 6 34.2 17.4

Sample Output

1 3 6
38.3 38.3

题目大意:你在沙漠中探险。由于沙漠非常热,你希望尽可能地降低旅途中的最高温度。沙漠中有一些绿洲,可以用来休息,而绿洲之间的道路则是温度不低的沙漠。你的任务是选择一条从起点到终点(起点和终点均为绿洲)的路线,使得途经的道路的最高温度尽量低。如果有多个路线满足此条件,则选择长度最短的那一条。

解题思路:先用最小生成树求出最小瓶颈边(以温度为标准),然后将小于等于最小瓶颈边的边都加入另一张图(以长度为标准),接着在该图上求最短路,记录一下路径就行了。

#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <cstdlib>#include <queue>using namespace std;typedef long long ll;const int N = 105;const int M = 10005;const int INF = 0x3f3f3f3f;int n, m, s, t;int f[N];struct EEdge{    int u, v;    double r, d;}edges[M];struct HeapNode{    double d;    int u;      bool operator < (const HeapNode& rhs) const{          return d > rhs.d;      }  };  struct Edge{      int from,to;      double dist;  };  struct Dijkstra{      vector<Edge> edges;    //边列表      vector<int> G[M];      //每个结点出发的边编号(从0开始编号)      bool done[N];          //是否已永久标号      double d[N];          //s到各个点的距离      int pre[N];    void init() {          for(int i = 0; i <= M; i++) G[i].clear();//清空邻接表          edges.clear();//清空边表          memset(pre, 0, sizeof(pre));    }      void addEdge(int from, int to, double dist) {           //如果是无向图,每条无向边需调用两次AddEdge          edges.push_back((Edge){from, to, dist});          edges.push_back((Edge){to, from, dist});        int h = edges.size();          G[from].push_back(h - 2);          G[to].push_back(h - 1);    }      void dijkstra(int s) {//求s到所有点的距离          priority_queue<HeapNode> Q;          for(int i = 0; i <= n; i++) d[i] = INF * 1.0;          d[s] = 0.0;          memset(done, 0, sizeof(done));          Q.push((HeapNode){0, s});          while(!Q.empty()){              HeapNode x = Q.top(); Q.pop();              int u = x.u;              if(done[u]) continue;              done[u] = true;              for(int i = 0; i < G[u].size(); i++){                  Edge& e = edges[G[u][i]];                  if(d[e.to] > d[u] + e.dist){                      pre[e.to] = G[u][i];                    d[e.to] = d[u] + e.dist;                      Q.push((HeapNode){d[e.to], e.to});                  }              }          }      }      void print(int s, int t) {        if (s == t) {            printf("%d", t);                return;        }           print(s, edges[pre[t]].from);        printf(" %d", t);    }}dij;  int find(int x) {    return x == f[x] ? x : f[x] = find(f[x]);}int cmp(EEdge a, EEdge b) {    if (a.r != b.r) return a.r < b.r;    return a.d < b.d;}void init() {    for (int i = 0; i <= n; i++) f[i] = i;}double kruskal() {    sort(edges, edges + m, cmp);    double Max;    for (int i = 0; i < m; i++) {        int x = find(edges[i].u), y = find(edges[i].v);        if (x != y) {            f[x] = y;               if (find(s) == find(t)) {                Max = edges[i].r;                break;            }        }    }    return Max;}void input() {    scanf("%d %d", &s, &t);    int a, b;    double c, d;    for (int i = 0; i < m; i++) {        scanf("%d %d", &a, &b);             scanf("%lf %lf", &c, &d);        edges[i].u = a, edges[i].v = b;        edges[i].r = c, edges[i].d = d;    }}void solve() {    double temp = kruskal();    for (int i = 0; i < m; i++) {        if (edges[i].r <= temp) {            dij.addEdge(edges[i].u, edges[i].v, edges[i].d);        }       }       dij.dijkstra(s);    dij.print(s, t);    puts("");    printf("%.1lf %.1lf\n", dij.d[t], temp);}int main() {    while (scanf("%d %d", &n, &m) == 2) {        dij.init();        init();        input();            solve();    }    return 0;}
0 0
原创粉丝点击