• 最短路 || 分层图最短路


    在对可以任选的一部分边或点有限制的时候,可以建分层图

    HDU 3499

    题意:n个城市有m条价格不同的航线,从s到t,可以选择一条边价格减半,求最小花费

    建两层图,每一层图里连边,两层图里连边

    #include <map>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    const int maxn = 200010;
    const int maxm = 1500100;
    const LL INF = 1000000000100LL;
    map<string, int> mp;
    int head[maxn], nxt[maxm], tot;
    int vis[maxn];
    LL dis[maxn];
    struct Edge
    {
        int t;
        LL d;
        Edge () {}
        Edge(int t, LL d) : t(t), d(d) {};
    } l[maxm];
    void build(int f, int t, LL d)
    {
        l[++tot] = Edge(t, d);
        nxt[tot] = head[f];
        head[f] = tot;
    }
    void init()
    {
        tot = 0;
        memset(head, -1, sizeof(head));
        mp.clear();
    }
    struct node
    {
        int u;
        LL d;
        node () {}
        node(int u, LL d) : u(u), d(d) {};
        bool operator < (const node &a) const
        {
            return d > a.d;
        }
    };
    LL dij(int s, int t)
    {
        //bool operator < (node a, node b) {return a.d > b.d; }
        priority_queue<node> q;
        for(int i = 0; i < maxn; i++) dis[i] = INF;
        memset(vis, 0, sizeof(vis));
        dis[s] = 0LL;
        q.push(node(s, 0LL));
        while(q.size())
        {
            int u = q.top().u;
            q.pop();
            if(vis[u]) continue;
            vis[u] = 1;
            for(int i = head[u]; ~i; i = nxt[i])
            {
                int v = l[i].t;
                if(dis[v] > dis[u] + l[i].d)
                {
                    dis[v] = dis[u] + l[i].d;
                    q.push(node(v, dis[v]));
                }
            }
        }
        if(dis[t] == INF) return -1;
        return dis[t];
    }
    int main()
    {
        int n, m;
        while(~scanf("%d%d", &n, &m))
        {
            int idx = 0;
            init();
            for(int i = 0; i < m; i++)
            {
                char str1[13], str2[13];
                LL c;
                scanf(" %s %s %lld", str1, str2, &c);
                if(mp.find(str1) == mp.end()) mp[str1] = idx++;
                if(mp.find(str2) == mp.end()) mp[str2] = idx++;
                build(mp[str1], mp[str2], c);
                build(mp[str1]+n, mp[str2]+n, c);
                build(mp[str1], mp[str2]+n, c/2);
            }
            char st[13], ed[13];
            scanf(" %s %s", st, ed);
            printf("%lld
    ", dij(mp[st], mp[ed]+n));
        }
        return 0;
    }
    View Code

    DP做法

    #include <map>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    const int maxn = 100010;
    const int maxm = 500100;
    const LL INF = 1000000000100LL;
    map<string, int> mp;
    int head[maxn], nxt[maxm], tot;
    int vis[maxn];
    LL dis[maxn][2];
    struct Edge
    {
        int t;
        LL d;
        Edge () {}
        Edge(int t, LL d) : t(t), d(d) {};
    } l[maxm];
    void build(int f, int t, LL d)
    {
        l[++tot] = Edge(t, d);
        nxt[tot] = head[f];
        head[f] = tot;
    }
    void init()
    {
        tot = 0;
        memset(head, -1, sizeof(head));
        mp.clear();
    }
    struct node
    {
        int u;
        LL d;
        node () {}
        node(int u, LL d) : u(u), d(d) {};
        bool operator < (const node &a) const
        {
            return d > a.d;
        }
    };
    LL dij(int s, int t)
    {
        //bool operator < (node a, node b) {return a.d > b.d; }
        priority_queue<node> q;
        for(int i = 0; i < maxn; i++) dis[i][0] = dis[i][1] = INF;
        memset(vis, 0, sizeof(vis));
        dis[s][0] = 0LL;
        dis[s][1] = 0LL;
        q.push(node(s, 0LL));
        while(q.size())
        {
            int u = q.top().u;
            q.pop();
            if(vis[u]) continue;
            vis[u] = 1;
            for(int i = head[u]; ~i; i = nxt[i])
            {
                int v = l[i].t;
                if(dis[v][0] > dis[u][0] + l[i].d)
                {
                    dis[v][0] = dis[u][0] + l[i].d;
                    q.push(node(v, dis[v][0]));
                }
                if(dis[v][1] > dis[u][0] + l[i].d/2 || dis[v][1] > dis[u][1] + l[i].d)
                {
                    dis[v][1] = min(dis[u][0] + l[i].d/2, dis[u][1] + l[i].d);
                    q.push(node(v, dis[v][1]));
                }
            }
        }
        //printf("%d %d %lld
    ",s,t, dis[t][0]);
        if(dis[t][1] == INF || s == t) return -1;
        return min(dis[t][0], dis[t][1]);
    }
    
    int main()
    {
        int n, m;
        while(~scanf("%d%d", &n, &m))
        {
            int idx = 0;
            init();
            for(int i = 0; i < m; i++)
            {
                char str1[13], str2[13];
                LL c;
                scanf(" %s %s %lld", str1, str2, &c);
                if(mp.find(str1) == mp.end()) mp[str1] = idx++;
                if(mp.find(str2) == mp.end()) mp[str2] = idx++;
                build(mp[str1], mp[str2], c);
            }
            char st[13], ed[13];
            scanf(" %s %s", st, ed);
            printf("%lld
    ", dij(mp[st], mp[ed]));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    MT【90】图论基础知识及相关例题
    MT【89】三棱锥的体积公式
    Qt之界面实现技巧
    QCompleter自动补全
    Qt之开机自启动
    Qt之日志输出文件
    相遇Qt5
    QT中的pro文件的编写
    qt下的跨目录多工程编译
    用QT打开网页
  • 原文地址:https://www.cnblogs.com/pinkglightning/p/9692639.html
Copyright © 2020-2023  润新知