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;
    
    }
    
    
  • 相关阅读:
    转 du: 查看目录大小
    conductor v3 docker-compose 运行
    使用parquetjs 创建parquet 文件
    dremio 数据格式的一些说明
    集成minio sidekick & console 的测试
    hermes golang email 模版包
    gothic 类似gotrue 的服务
    cube.js 官方关于cube store 的一些实践说明
    dremio sql server 链接问题
    使用sbt-native-packager 构建通用的scala 软件包
  • 原文地址:https://www.cnblogs.com/ruanbaiQAQ/p/14284425.html
Copyright © 2011-2022 走看看