zoukankan      html  css  js  c++  java
  • CodeForce 1473E. Minimum Path(分层图最短路)

    题目链接

    https://codeforces.com/contest/1473/problem/E

    题意

    给定一张带权无向无环图,求(1)号点到其他点的最小路径权值。
    路径的权值等于路径上所有边的权值和加上路径上最小的边减去最大的边。

    思路

    分层图最短路,减去最大值就看成一条边免费,免费的边建一层,加上最小值就看成双倍贡献,双倍的边建一层, 然后还有只有一条边的情况单独一层(比赛没考虑这点,看出是分层图少了一层没做出来!)。

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e6 + 50;
    typedef long long ll;
    const ll INF = 0x3f3f3f3f3f3f3f3f;
    int n, m, k;
    int head[maxn], vis[maxn];
    int cnt;
    ll dis[maxn];
    struct edge{
        int to, next;
        ll w;
    };
    edge es[maxn << 2];
    void init(int n)
    {
        memset(vis,0,sizeof(vis));
        memset(head,-1,sizeof(head));
        fill(dis, dis + 4 * n + 1, INF);
        cnt = 0;
    }
    void add(int u,int v,ll w)
    {
        es[cnt].to = v;
        es[cnt].w = w;
        es[cnt].next = head[u];
        head[u] = cnt++;
    }
    void ins(int u, int v, ll w){
        add(u ,v, w); add(v, u, w);
    }
    struct node
    {
        int pos;
        ll cost;
        node(int pos, ll cost):pos(pos),cost(cost){}
        friend bool operator < (node a,node b){
            return a.cost > b.cost;
        }
    };
    void dijkstra(int st)
    {
        priority_queue<node> q;
        dis[st] = 0;
        q.push(node(st,0));
        while(!q.empty())
        {
            node now = q.top();
            q.pop();
            int t = now.pos;
            if(vis[t]) continue;
            vis[t] = 1;
            for(int i = head[t];i != -1;i = es[i].next)
            {
                int v = es[i].to;
                if(dis[v] >  dis[t] + es[i].w)
                {
                    dis[v] =  dis[t] + es[i].w;
                    q.push(node(v, dis[v]));
                }
            }
        }
    }
    int main()
    {
        std::ios::sync_with_stdio(false);
        cin >> n >> m;
        init(n);
        for(int i = 1;i <= m;i++){
            int u, v;
            ll w;
            cin >> u >> v >> w;
            for(int j = 0;j < 2;j++){
                //每层的图
                add(u, v, w);
                add(u + n, v + n, w);
                add(u + 2 * n, v + 2 * n, w);
                add(u + 3 * n, v + 3 * n, w);
                //选择max
                add(u, v + n, 0);
                add(u + 2 * n, v + 3 * n, 0);
                //选择min
                add(u, v + 2 * n, 2LL * w);
                add(u + n, v + 3 * n, 2LL * w);
                //选择 min, max
                add(u, v + 3 * n, w);
                swap(u, v);
            }
    
        }
        dijkstra(1);
        for(int i = 2;i <= n;i++){
            ll ans = min(dis[i], dis[i + 3 * n]);
            cout << ans << " ";
        }
        return 0;
    }
    
    
  • 相关阅读:
    人生转折点:弃文从理
    人生第一站:大三暑假实习僧
    监听器启动顺序和java常见注解
    java常识和好玩的注释
    182. Duplicate Emails (Easy)
    181. Employees Earning More Than Their Managers (Easy)
    180. Consecutive Numbers (Medium)
    178. Rank Scores (Medium)
    177. Nth Highest Salary (Medium)
    176. Second Highest Salary(Easy)
  • 原文地址:https://www.cnblogs.com/Carered/p/14280226.html
Copyright © 2011-2022 走看看