uva10816 Travel in Desert(MST + 最短路)

题意:一群人在沙漠中,给定了n个点,m条路,双向的。每条路有一定的长度且路上的温度也不一样。现在这群人想从s到t去,要使路径中的最高温度最低,有多条路径的情况下选择路程最短的,输出路径,最高温度,路程。

思路:算是一道考验代码的图论题,并不是很难。可以想到最高温度最低,就用贪心(MST)直到s,t连通和保留温度t相同的边。
然后在这些边上做最短路并保存路径打印出来。

/***************************************** Author :Crazy_AC(JamesQi) Time :2016 File Name : *****************************************/
// #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <climits>
using namespace std;
#define MEM(x,y) memset(x, y,sizeof x)
#define pk push_back
#define lson rt << 1
#define rson rt << 1 | 1
#define bug cout << "BUG HERE\n"
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,double> ii;
typedef pair<ii,int> iii;
const double eps = 1e-8;
const double pi = 4 * atan(1);
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int nCase = 0;
int dcmp(double x){//精度正负、0的判断
    if (fabs(x) < eps) return 0;
    return x < 0?-1:1;
}
inline int read(){
    char c = getchar();
    while (!isdigit(c)) c = getchar();
    int x = 0;
    while (isdigit(c)) {
        x = x * 10 + c - '0';
        c = getchar();
    }
    return x;
}
const int maxn = 123;
const int maxm = 12345;
struct Edge {
    int u, v;
    double t, d;

    void read() {
        scanf("%d %d %lf %lf", &u, &v, &t, &d);
    }

    bool operator < (const Edge& rhs) const {
        return t < rhs.t || (t == rhs.t && d < rhs.d);
    }
}edges[maxm];
struct state {
    int u;
    double d;

    state(int u,double d) {
        this->u = u;
        this->d = d;
    } 

    bool operator < (const state& rhs) const {
        return d > rhs.d;
    }
};
int n, m;
int S, T;
vector<ii> G[maxn];
vector<int> ans;
int f[maxn];
int find(int x) {
    return f[x] == x ? x : f[x] = find(f[x]);
}
void input() {
    scanf("%d %d", &S, &T);
    for (int i = 1;i <= n;++i)
        G[i].clear(), f[i] = i;
    for (int i = 0;i < m;++i)
        edges[i].read();
    sort(edges, edges + m);
}
double dis[maxn];
int vis[maxn];
int p[maxn];

void put(int u) {
    if (u == 0) return ;
    put(p[u]);

    ans.push_back(u);
    return ;
}

double dijk() {
    priority_queue<state> que;
    for (int i = 0;i <= n;++i)
        dis[i] = inf;
    memset(vis, 0,sizeof vis);
    dis[S] = p[S] = 0;
    que.push(state(S, dis[S]));

    while(!que.empty()) {
        int u = que.top().u;
        que.pop();

        if (vis[u]) continue;
        vis[u] = 1;

        for (int i = 0;i < G[u].size();++i) {
            int v = G[u][i].first;
            double d = G[u][i].second;

            if (dis[v] > dis[u] + d) {
                dis[v] = dis[u] + d;
                p[v] = u;
                que.push(state(v, dis[v]));
            }
        }
    }

    ans.clear();
    put(T);

    for (int i = 0;i < ans.size();++i) 
        printf("%d%c", ans[i], i == ans.size() - 1?'\n':' ');

    return dis[T];
}

void solve() {
    bool ok = false;
    double temp;

    for (int i = 0;i < m;++i) {
        if (ok && edges[i].t - edges[i-1].t > eps) break;
        int u = edges[i].u;
        int v = edges[i].v;
        int t1 = find(u);
        int t2 = find(v);

        G[u].push_back(ii(v, edges[i].d));
        G[v].push_back(ii(u, edges[i].d));

        if (t1 != t2)
            f[t1] = t2;

        if (find(S) == find(T)) {
            ok = true;
            temp = edges[i].t;
        }
    }
    double o = dijk();
    printf("%.1lf %.1lf\n", o, temp);
}

int main(int argc, const char * argv[])
{   
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    while(scanf("%d %d", &n, &m) != EOF) {
        input();
        solve();
    }
    return 0;
}

你可能感兴趣的:(MST-最短路)