zoukankan      html  css  js  c++  java
  • 题解:CF1473 E. Minimum Path

    题面

    Translation

    有一条路径上共有 (k) 条边,第 (i) 条边边权为 (w_i) ,定义该路径权值为 (sumlimits_{i=1}^{k}{w_i} - maxlimits_{i=1}^{k}{w_i} + minlimits_{i=1}^{k}{w_i}) ,给一张 (n) 条边, (m) 条边的无向连通图,求从 (1) 号点到 (i(2leq i leq n)) 号点路径权值的最小值。

    Solution

    容易发现对于一条路径而言,该式子的含义就是将最大的一条边权改成 0 ,将最小的一条边权翻成两倍。

    再进一步思考,若是把式子改为 (sumlimits_{i=1}^{k}{w_i} - w_p + w_q) ,其中 (p) , (q) 是任意两条边,那么要求的答案就是改完后的式子的最小值。

    发现有两步特殊操作,一步是将一个边权减一,另一步是将一个边权翻倍。

    可以使用分层图跑最短路解决。

    发现两步操作没有先后顺序,所以要开 4 层图,第 1 层放原图,第 2 层放已经有被清零的边权的图,第 3 层放已经有翻倍边权的图,最后一层就是答案。

    对于一个点 (p) ,约定在第 (i) 层的序号表示为 (p+(i-1) imes n)

    具体连边操作(对于一条 (u longrightarrow v) ,权值为 (w) 的原图边):

    (u longrightarrow v) 边权为 (w)

    (u longrightarrow v+n) 边权为 (0)

    (u longrightarrow v+n imes 2) 边权为 (w imes 2)

    (u longrightarrow v+n imes 3) 边权为 (w) (路径上边数为 1 的特殊情况)

    (u+n longrightarrow v+n) 边权为 (w)

    (u+n longrightarrow v+n imes 3) 边权为 (w imes 2)

    (u+n imes 2 longrightarrow v imes 2) 边权为 (w)

    (u+n imes 2 longrightarrow v imes 3) 边权为 (0)

    (u+n imes 3 longrightarrow v imes 3) 边权为 (w)

    Code(C++):

    // E. Minimum Path
    #include<bits/stdc++.h>
    #define forn(i,s,t) for(register int i=(s);i<=(t);++i)
    using namespace std;
    typedef long long LL;
    const int N = 8e5+3, M = 1e7+3;
    struct List{int dir, nxt; LL lng;} E[M];
    int G[N];
    inline void Add(int u, int v, LL w) {
    	static int cnt;
    	E[++cnt] = (List){v, G[u], w}; G[u] = cnt;
    }
    int n, m; LL dis[N];
    int main() {
    	scanf("%d%d", &n, &m);
    	forn(i,1,m) {
    		static int u, v; static LL w;
    		scanf("%d%d%lld", &u, &v, &w);
    		Add(u, v, w), Add(v, u, w);
    		Add(u, v+n, 0), Add(v, u+n, 0);
    		Add(u, v+n*2, w<<1), Add(v, u+n*2, w<<1);
    		Add(u, v+n*3, w), Add(v, u+n*3, w);
    		Add(u+n, v+n, w), Add(v+n, u+n, w);
    		Add(u+n, v+n*3, w<<1), Add(v+n, u+n*3, w<<1);
    		Add(u+2*n, v+2*n, w), Add(v+2*n, u+2*n, w);
    		Add(u+2*n, v+3*n, 0), Add(v+2*n, u+3*n, 0);
    		Add(u+3*n, v+3*n, w), Add(v+3*n, u+3*n, w);
    	}
    	memset(dis, -1, sizeof dis);
    	static priority_queue<pair<LL, int> > q;
    	q.push(make_pair(0ll, 1));
    	while(!q.empty()) {
    		static int u;
    		u = q.top().second;
    		if(dis[u] != -1) {q.pop(); continue ;}
    		dis[u] = - q.top().first; q.pop();
    		for(int i=G[u];i;i=E[i].nxt) 
    			if(dis[E[i].dir] == -1) 
    				q.push(make_pair(-dis[u]-E[i].lng, E[i].dir));
    	}
    	forn(i,2,n) printf("%lld ", dis[i + 3*n]);
    	return 0;
    }
    

    Edu Round 的质量很高,但是不会网络流和 FFT ,这场的 F 、 G 只能以后再补了。。。

  • 相关阅读:
    转 | 禁忌搜索算法(Tabu Search)求解带时间窗的车辆路径规划问题详解(附Java代码)
    Branch and price and cut求解传统VRP问题以及VRPTW问题
    标号法(label-setting algorithm)求解带时间窗的最短路问题(ESPPRC)
    运筹学从何学起?如何快速入门精确式算法?
    转 | 模拟退火算法(SA)和迭代局部搜索(ILS)求解TSP的Java代码分享
    用Python画论文折线图、曲线图?几个代码模板轻松搞定!
    45. 截取“测试数据”后面的内容
    44. 更改oracle字符集编码american_america.zh16gbk 改为 SIMPLIFIED CHINESE_CHINA.ZHS16GBK
    18. 浏览器关闭页面时弹出“确定要离开此面吗?”
    6. concat_ws用法
  • 原文地址:https://www.cnblogs.com/Ax-Dea/p/14355399.html
Copyright © 2011-2022 走看看