zoukankan      html  css  js  c++  java
  • uva 10816 Travel in Desert(简单的好题~两种方法)

    题意:

    给出 一个图

    点与点之间的路径上有两个权值 路径长度和温度

    要求在所走路径中的温度的最大值最小的前提下 走最短路径

    解题思路1:

    首先用 最小生成树 的方法走出 最小瓶颈路 。把在这期间用到的全部温度小于 路径上最大温度 的边存下来,作为接下来求最短路径的图。

    在新生成的图中求最短路径就可以;

    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    
    const int maxm = 10005;
    const int maxn = 105;
    
    struct Edge{
        int u,v;
        double dist,tm;
        void read(){
            scanf("%d%d%lf%lf",&u,&v,&tm,&dist);
            u--;v--;
        }
        bool operator<(const Edge et)const{
            if(tm != et.tm) return tm < et.tm;
            else return dist < et.dist;
        }
    }e[maxm];
    int n,m,s,t;
    int parent[maxn];
    vector<Edge> g[maxn];
    
    
    void init(){
        scanf("%d%d",&s,&t);
        s--;t--;
        for(int i = 0; i < m; i++){
            e[i].read();
        }
        for(int i = 0; i < n; i++){
                g[i].clear();
        }
    }
    int find(int x){
        if(parent[x] == x) return x;
        else return parent[x] = find(parent[x]);
    }
    
    
    const int INF = 0x3f3f3f3f;
    const int MAXNODE = 105;
    
    struct Edge2 {
        int u, v;
        double dist;
        Edge2() {}
        Edge2(int u, int v, double dist) {
            this->u = u;
            this->v = v;
            this->dist = dist;
        }
    };
    struct HeapNode {
        double d;
        int u;
        HeapNode() {}
        HeapNode(double d, int u) {
            this->d = d;
            this->u = u;
        }
        bool operator < (const HeapNode& c) const {
            return d > c.d;
        }
    };
    struct Dijkstra {
        int n, m;
        vector<Edge2> edges;
        vector<int> g[MAXNODE];
        bool done[MAXNODE];
        double d[MAXNODE];
        int p[MAXNODE];
    
        void init(int tot) {
            n = tot;
            for (int i = 0; i < n; i++)
                g[i].clear();
            edges.clear();
        }
    
        void add_Edge(int u, int v, double dist) {
            edges.push_back(Edge2(u, v, dist));
            m = edges.size();
            g[u].push_back(m - 1);
        }
    
        void print(int s, int e) {//shun xu
            if (s == e) {
                printf("%d", e + 1);
                return;
            }
            print(s, edges[p[e]].u);
            printf(" %d", e + 1);
        }
    
        void print2(int s, int e) {//ni xu
            if (s == e) {
                printf("%d", e + 1);
                return;
            }
            printf("%d ", e + 1);
            print2(s, edges[p[e]].u);
        }
    
        void dijkstra(int s) {
            priority_queue<HeapNode> Q;
            for (int i = 0; i < n; i++) d[i] = INF*1.0;
            d[s] = 0.0;
            memset(done, false, 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++) {
                    Edge2& e = edges[g[u][i]];
                    if (d[e.v] > d[u] + e.dist) {
                        d[e.v] = d[u] + e.dist;
                        p[e.v] = g[u][i];
                        Q.push(HeapNode(d[e.v], e.v));
                    }
                }
            }
        }
    } graph;
    
    void solve(){
    //    printf("...
    ");
        double ans = 0;
        sort(e,e+m);
    
    //    for(int i = 0; i < m; i++){
    //        printf("%.1lf %.1lf %d %d
    ",e[i].dist,e[i].tm,e[i].u,e[i].v);
    //    }
        for(int i = 0; i < n; i++) parent[i] = i;
    
        double max_tm = 500.0;
        graph.init(n);
        for(int i = 0; i < m; i++){
            if(e[i].tm > max_tm) break;
            graph.add_Edge(e[i].u,e[i].v,e[i].dist);
            graph.add_Edge(e[i].v,e[i].u,e[i].dist);
    
            int pu = find(e[i].u);
            int pv = find(e[i].v);
            if(pu == pv) continue;
            parent[pu] = pv;
    
            if(find(s) == find(t)){
                max_tm = e[i].tm;
            }
        }
    
        graph.dijkstra(s);
        graph.print(s,t);
        printf("
    ");
        printf("%.1lf %.1lf
    ",graph.d[t],max_tm);
    
    }
    int main(){
        while(scanf("%d%d",&n,&m) != EOF){
            init();
            solve();
        }
        return 0;
    }
    

    解题思路二:

    把原图存下来,然后二分温度,再把全部小于温度mid的边拿出来构成一个新图,然后继续dijkstra求最短路,有成功和不成功两种结果,找到能成功的最小温度就可以

    code

    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <queue>
    using namespace std;
    
    const int MAXNODE = 105;
    const int MAXEDGE = 20005;
    
    typedef double Type;
    const Type INF = 0x3f3f3f3f;
    
    struct Edge {
        int u, v;
        Type dist, d;
        Edge() {}
        Edge(int u, int v, Type dist, Type d = 0) {
            this->u = u;
            this->v = v;
            this->dist = dist;
            this->d = d;
        }
        void read() {
            scanf("%d%d%lf%lf", &u, &v, &d, &dist);
            u--; v--;
        }
    };
    
    struct HeapNode {
        Type d;
        int u;
        HeapNode() {}
        HeapNode(Type d, int u) {
            this->d = d;
            this->u = u;
        }
        bool operator < (const HeapNode& c) const {
            return d > c.d;
        }
    };
    
    int n, m, s, t;
    
    struct Dijkstra {
        int n, m;
        Edge edges[MAXEDGE];
        int first[MAXNODE];
        int next[MAXEDGE];
        bool done[MAXNODE];
        Type d[MAXNODE];
        int p[MAXNODE];
    
        void init(int n) {
            this->n = n;
            memset(first, -1, sizeof(first));
            m = 0;
        }
    
        void add_Edge(int u, int v, Type dist) {
            edges[m] = Edge(u, v, dist);
            next[m] = first[u];
            first[u] = m++;
        }
    
        void add_Edge(Edge e) {
            edges[m] = e;
            next[m] = first[e.u];
            first[e.u] = m++;
        }
        void print(int e) {//shun xu
            if (p[e] == -1) {
                printf("%d", e + 1);
                return;
            }
            print(edges[p[e]].u);
            printf(" %d", e + 1);
        }
    
        void print2(int e) {//ni xu
            if (p[e] == -1) {
                printf("%d
    ", e + 1);
                return;
            }
            printf("%d ", e + 1);
            print2(edges[p[e]].u);
        }
    
        bool dijkstra(int s, int t) {
            priority_queue<HeapNode> Q;
            for (int i = 0; i < n; i++) d[i] = INF;
            d[s] = 0;
            p[s] = -1;
            memset(done, false, sizeof(done));
            Q.push(HeapNode(0, s));
            while (!Q.empty()) {
                HeapNode x = Q.top(); Q.pop();
                int u = x.u;
                if (u == t)
                    return true;
                if (done[u]) continue;
                done[u] = true;
                for (int i = first[u]; i != -1; i = next[i]) {
                    Edge& e = edges[i];
                    if (d[e.v] > d[u] + e.dist) {
                        d[e.v] = d[u] + e.dist;
                        p[e.v] = i;
                        Q.push(HeapNode(d[e.v], e.v));
                    }
                }
            }
            return false;
        }
    } gao;
    
    Edge e[MAXEDGE];
    
    bool judge(double mid) {
        gao.init(n);
        for (int i = 0; i < m; i++) {
            if (e[i].d > mid) continue;
            gao.add_Edge(e[i]);
            gao.add_Edge(Edge(e[i].v, e[i].u, e[i].dist, e[i].d));
        }
        if (gao.dijkstra(s, t)) return true;
        return false;
    }
    
    int main() {
        while (~scanf("%d%d", &n, &m)) {
            scanf("%d%d", &s, &t);
            s--; t--;
            for (int i = 0; i < m; i++)
                e[i].read();
            double l = 0, r = 50, mid;
            while (r - l > 1e-8) {
                mid = (l + r) / 2;
                if (judge(mid)) r = mid;
                else l = mid;
            }
            if (judge(r)) {
                gao.print(t); printf("
    ");
                printf("%.1lf %.1lf
    ", gao.d[t], mid);
            }
        }
        return 0;
    }
    
    二分在非常多情况下都是非常好用的一种方法~


  • 相关阅读:
    C#中的Dictionary字典类介绍
    SQL server 2008r2 file is corrupt
    web service接口 wsdl和asmx有什么区别
    ascx
    C++: C++函数声明的时候后面加const
    C++三种野指针及应对/内存泄露
    C++构造和析构的顺序
    atan2()如何转换为角度
    C++11左值引用和右值引用
    C++ STL详解
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5417952.html
Copyright © 2011-2022 走看看