• E


    题意:给你一张无向图,无重边无自环。给出定义:对于一条路径(不一定是简单路径,比如对于图(1-2-3,1->2->3->2)这种有些边走了2次的就不是简单路径),他的路径总权值为路径上每一条经过边的和减去路径上最大的边权加上路径上最小的边权。让你求1点到每个点的最小满足上述条件的路径权值。

    做法:由于不知道从1到某一点的路径究竟是怎么样的(不知道经过哪些点,不知道最大最小值,不知道是否为简单路径。。。)。但这条路径中只有一个最大值和一个最小值,对于某一条边我们可以得到4个状态:

    ①这条边即不是最大值也不是最小值。

    ②这条边是最大值

    ③这条边是最小值

    ④这条边即是最大值也是最小值

    这样可以用类似dp的方法,通过将图分层,把所有可行状态枚举出来去更新每个点的答案。


    代码有两种写法:

    一:dis分层

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define fastio ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
    const ll inf = 1e18 + 7;
    const int maxn = 2e5 + 10;
    
    struct Node {
        ll dis;
        int from, v1, v2;
        friend bool operator <(Node x, Node y){
            return x.dis > y.dis;
        }
    };
    
    int head[maxn], edge_cnt = 0;
    
    struct edge {
        int to;
        ll cost;
        int next;
    }e[maxn << 1];
    
    void add(int from, int to, ll cost)
    {
        e[++edge_cnt] = { to,cost,head[from] };
        head[from] = edge_cnt;
    }
    
    ll dis[maxn][2][2];
    int n;
    void dij()
    {
        priority_queue<Node>q;
        for (int i = 1; i <= n; i++)
            for (int j = 0; j <= 1; j++)
                for (int k = 0; k <= 1; k++)
                    dis[i][j][k] = inf;
        q.push({ 0,1,0,0 });
        while (!q.empty())
        {
            Node now = q.top();
            q.pop();
            int from = now.from; ll dist = now.dis;
            bool v1 = now.v1, v2 = now.v2;
            if (now.dis > dis[from][v1][v2])continue;
            for (int i = head[from]; ~i; i = e[i].next)
            {
                int to = e[i].to; ll cost = e[i].cost;
                if (dis[to][v1][v2] > dist + cost)
                {
                    dis[to][v1][v2] = dist + cost;
                    q.push({ dis[to][v1][v2],to,v1,v2 });
                }
                if (!v1 && dis[to][1][v2] > dist)
                {
                    dis[to][1][v2] = dist;
                    q.push({ dis[to][1][v2],to,1,v2 });
                }
                if (!v2 && dis[to][v1][1] > dist + 2 * cost)
                {
                    dis[to][v1][1] = dist + 2 * cost;
                    q.push({ dis[to][v1][1],to,v1,1 });
                }
                if (!v1 && !v2 && dis[to][1][1] > dist + cost)
                {
                    dis[to][1][1] = dist + cost;
                    q.push({ dis[to][1][1],to,1,1 });
                }
            }
        }
        for (int i = 2; i <= n; i++)
            cout << dis[i][1][1] << " ";
    }
    
    int main()
    {
    	//freopen("C:\test.txt", "r", stdin);
        fastio;
        memset(head, -1, sizeof(head));
        int m;
        cin >> n >> m;
        while (m--)
        {
            int x, y, z;
            cin >> x >> y >> z;
            add(x, y, z);
            add(y, x, z);
        }
        dij();
    
        return 0;
    
    }
    
    

    二:开4倍的点

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define fastio ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
    const ll inf = 1e18 + 7;
    const int maxn = 2e5 + 10;
    
    struct Node {
        ll dis;
        int from;
        friend bool operator <(Node x, Node y){
            return x.dis > y.dis;
        }
    };
    
    int head[4 * maxn], edge_cnt = 0;
    
    struct edge {
        int to;
        ll cost;
        int next;
    }e[maxn * 18 + 1];
    
    void add(int from, int to, ll cost)
    {
        e[++edge_cnt] = { to,cost,head[from] };
        head[from] = edge_cnt;
    }
    
    ll dis[4*maxn];
    int n;
    void dij()
    {
        priority_queue<Node>q;
        for (int i = 1; i <= 4 * n; i++)
                    dis[i] = inf;
        dis[1] = 0;
        q.push({ 0,1});
        while (!q.empty())
        {
            Node now = q.top();
            q.pop();
            int from = now.from; ll dist = now.dis;
            if (now.dis > dis[from])continue;
            for (int i = head[from]; ~i; i = e[i].next)
            {
                int to = e[i].to; ll cost = e[i].cost;
                if (dis[to] > dist + cost)
                {
                    dis[to] = dist + cost;
                    q.push({ dis[to],to});
                }
            }
        }
        for (int i = 3 * n + 2; i <= 4 * n; i++)
            cout << dis[i] << " ";
    }
    
    int main()
    {
    	//freopen("C:\test.txt", "r", stdin);
        fastio;
        memset(head, -1, sizeof(head));
        int m;
        cin >> n >> m;
        while (m--)
        {
            int x, y, z;
            cin >> x >> y >> z;
            add(x, y, z);
            add(y, x, z);
            add(x + n, y + n, z);
            add(y + n, x + n, z);
            add(x + 2 * n, y + 2 * n, z);
            add(y + 2 * n, x + 2 * n, z);
            add(x + 3 * n, y + 3 * n, z);
            add(y + 3 * n, x + 3 * n, z);
            add(x, y + n, 0);
            add(y, x + n, 0);
            add(x, y + 2 * n, 2 * z);
            add(y, x + 2 * n, 2 * z);
            add(x, y + 3 * n, z);
            add(y, x + 3 * n, z);
            add(x + n, y + 3 * n, 2 * z);
            add(y + n, x + 3 * n, 2 * z);
            add(x + 2 * n, y + 3 * n, 0);
            add(y + 2 * n, x + 3 * n, 0);
    
        }
        dij();
    
        return 0;
    
    }
    
    
  • 相关阅读:
    利用pip批量升级packages
    基于cx_freeze编译PyQt4程序(numpy & scipy)
    利用Python读取Matlab的Mat文件内容
    在PyQt4中使用matplotlib
    个人Python常用Package及其安装
    python变量不能以数字打头
    Python Django开始
    Django 1.9 支持中文(转)
    Ubuntu1604中mysql的登录问题
    h3c防火墙的设置过程
  • 原文地址:https://www.cnblogs.com/ruanbaiQAQ/p/14284425.html
Copyright © 2020-2023  润新知