zoukankan      html  css  js  c++  java
  • 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;
    
    }
    
    
  • 相关阅读:
    Arcgis地理处理工具案例教程——批量提取多个栅格的范围边界矢量
    win10 windows10自动修复系统
    ArcGIS案例教程—E00格式批量导入成要素类
    Python正则表达式多行匹配问题
    学习ArcGIS开发的途径有哪些
    Arcgis空间分析案例教程——计算空间分布范围
    ArcGIS地理建模批处理教程——批量添加文件名作为字段值
    ArcGIS地理建模批处理教程——批量去除Z值和M值
    华为NM存储卡与Micro SD存储卡对比分析
    EDT
  • 原文地址:https://www.cnblogs.com/ruanbaiQAQ/p/14284425.html
Copyright © 2011-2022 走看看