UVA 10816 - Travel in Desert(最小瓶颈路+最短路)

题目链接 https://cn.vjudge.net/problem/UVA-10816

【题意】
给定一个n个点m条边的无向带权图(n<=100,m<=10000)以及起点和终点。边上有两种权值,路径长度和温度,要求在所走路径中的温度的最大值最小的前提下,走最短路径,输出路径以及最大温度和对应的长度.

【思路】
先用最小瓶颈路求出这个最大温度,然后将边权中所有温度不低于此温度的边加入新图中,在新图里跑最短路

#include<bits/stdc++.h>
using namespace std;

const int inf = 0x3f3f3f3f;
const int maxn = 1050;

struct Edge {
    int from,to;
    double dist;
    Edge(int f, int t, double d) :from(f), to(t), dist(d) {}
};

struct Edge2{
    int from,to;
    double r,d;
    Edge2(int f,int t,double rr,double dd):from(f),to(t),r(rr),d(dd){}
    bool operator<(const Edge2& e)const{
        return r<e.r;
    }
};

struct HeapNode {
    int u;
    double d;
    HeapNode(double dd, int uu) :d(dd), u(uu) {}
    bool operator < (const HeapNode& rhs) const {
        return d > rhs.d;
    }
};

struct Dijkstra {
    int n, m, s, t;           //点数和边数
    vector<Edge> edges; //边列表
    vector<int> g[maxn];//每个结点出发的边编号(从0开始)
    bool done[maxn];    //是否永久标号
    double d[maxn];     //s到各个点的距离
    int p[maxn];        //最短路中的上一条边

    void init(int n,int s,int t) {
        this->n = n;
        this->s = s;
        this->t = t;
        for (int i = 0; i < n; ++i) g[i].clear();   //清空邻接表
        edges.clear();  //清空边表
    }

    void add(int from, int to, double dist) {  //如果是无向图,每次加边调用两次
        edges.push_back(Edge(from, to, dist));
        m = edges.size();
        g[from].push_back(m - 1);
    }

    void dijkstra(int s) {  //s为源点
        priority_queue<HeapNode> que;
        for (int i = 0; i < n; ++i) d[i] = inf;
        d[s] = 0;
        memset(done, 0, sizeof(done));
        que.push(HeapNode(0, s));
        while (!que.empty()) {
            HeapNode x = que.top();
            que.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) {
                    d[e.to] = d[u] + e.dist;
                    p[e.to] = g[u][i];
                    que.push(HeapNode(d[e.to], e.to));
                }
            }
        }
    }
    void print(int x) {//递归打印以x为终点的最短路径
        if (x == s) {
            printf("%d",1+x);
            return;
        }
        Edge& e = edges[p[x]];
        print(e.from);
        printf(" %d",1+x);
    }
};

int n, m, s, t;
int par[maxn];
Dijkstra dij;
vector<Edge2> edges;

int find(int x){ return x==par[x]?x:par[x]=find(par[x]); }

double kruscal(){
    for(int i=0;i<n;++i) par[i]=i;
    sort(edges.begin(),edges.end());
    for(int i=0;i<m;++i){
        Edge2& e=edges[i];
        int x=find(e.from);
        int y=find(e.to);
        if(x!=y){
            par[x]=y;
            if(find(s)==find(t)) return e.r;
        }
    }
    return 0;
}

int main(){
    while(scanf("%d%d%d%d",&n,&m,&s,&t)==4){
        --s;--t;
        edges.clear();
        for(int i=0;i<m;++i){
            int u,v;
            double r,d;
            scanf("%d%d%lf%lf",&u,&v,&r,&d);
            --u;--v;
            edges.push_back(Edge2(u,v,r,d));
        }
        double ans=kruscal();
        dij.init(n,s,t);
        for(int i=0;i<m;++i){
            Edge2& e=edges[i];
            if(e.r<=ans){
                dij.add(e.from,e.to,e.d);
                dij.add(e.to,e.from,e.d);
            }
        }
        dij.dijkstra(s);
        dij.print(t);
        puts("");
        printf("%.1lf %.1lf\n",dij.d[t],ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xiao_k666/article/details/82665106