日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CF1473E Minimum Path(拆点+最短路)

發布時間:2023/12/3 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CF1473E Minimum Path(拆点+最短路) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

CF1473E Minimum Path

  • description
  • solution
  • code

description

題目鏈接

solution

看到 ∑i=1kwei\sum_{i=1}^kw_{e_i}i=1k?wei?? 的式子,就應該聯想到最短路

先考慮題目的弱化版,去掉 max,min\text{max},\text{min}max,min 的限制,變成一條路徑中的一條邊不要花費,一條邊花費加倍,再求最短路

貪心地 djikstra\text{djikstra}djikstra 跑最短路,發現是與原題對應的

dpi,j,k(j,k∈[0,1])dp_{i,j,k}(j,k\in[0,1])dpi,j,k?(j,k[0,1]) 表示到 iii 點時,jjj 是否加倍了一條邊,kkk 是否不要一條邊花費的最短路

則有轉移方程:
dpv,j,k=min?(dpv,j,k,dpu,j,k+wu,v)dp_{v,j,k}=\min(dp_{v,j,k},dp_{u,j,k}+w_{u,v}) dpv,j,k?=min(dpv,j,k?,dpu,j,k?+wu,v?)

dpv,1,k=min?(dpv,1,k,dpu,0,k+wu,v?2)dp_{v,1,k}=\min(dp_{v,1,k},dp_{u,0,k}+w_{u,v}*2) dpv,1,k?=min(dpv,1,k?,dpu,0,k?+wu,v??2)

dpv,j,1=min?(dpv,j,1,dpu,j,0)dp_{v,j,1}=\min(dp_{v,j,1},dp_{u,j,0}) dpv,j,1?=min(dpv,j,1?,dpu,j,0?)

最后答案為 min?(dpi,0,0,dpi,1,1)\min(dp_{i,0,0},dp_{i,1,1})min(dpi,0,0?,dpi,1,1?) 【路徑可能只有一條,max,min\text{max},\text{min}max,min 相互抵消】

實際上,也可以理解為把一個點拆成四個點后跑最短路

分別對應不同的操作,先加倍再不要,先不要再加倍

code

#include <queue> #include <cstdio> #include <vector> #include <iostream> using namespace std; #define int long long #define maxn 1000005 #define Pair pair < int, int > priority_queue < Pair, vector < Pair >, greater < Pair > > q; vector < Pair > G[maxn]; int n, m; int dis[maxn]; bool vis[maxn];void addedge( int u, int v, int w ) { G[u].push_back( { v, w } ); }signed main() {scanf( "%lld %lld", &n, &m );//分層圖 [1,n]表示第一層 [n+1,2n]表示使用加倍層 [2n+1,3n]表示使用不要層 [3n+1,4n]最后轉移的結果層 //對應操作是加倍后不要x->x+n->x+3n 不要后加倍x->x+2n->x+3n for( int i = 1, u, v, w;i <= m;i ++ ) {scanf( "%lld %lld %lld", &u, &v, &w );addedge( u, v, w ), addedge( v, u, w );addedge( u + n, v + n, w ), addedge( v + n, u + n, w );addedge( u + n * 2, v + n * 2, w ), addedge( v + n * 2, u + n * 2, w );addedge( u + n * 3, v + n * 3, w ), addedge( v + n * 3, u + n * 3, w );addedge( u, v + n, w * 2 ), addedge( v, u + n, w * 2 ); //加倍 addedge( u, v + n * 2, 0 ), addedge( v, u + n * 2, 0 ); //不要 addedge( u + n, v + n * 3, 0 ), addedge( v + n, u + n * 3, 0 ); //加倍后不要 addedge( u + n * 2, v + n * 3, w * 2 ), addedge( v + n * 2, u + n * 3, w * 2 ); //不要后加倍 }for( int i = 1;i <= ( n << 2 );i ++ ) dis[i] = 1e18;q.push( { dis[1] = 0, 1 } );while( ! q.empty() ) {int u = q.top().second; q.pop();if( vis[u] ) continue;vis[u] = 1;for( int i = 0;i < G[u].size();i ++ ) {int v = G[u][i].first, w = G[u][i].second;if( dis[v] > dis[u] + w ) {dis[v] = dis[u] + w;q.push( { dis[v], v } );}}}for( int i = 2;i <= n;i ++ ) printf( "%lld ", min( dis[i], dis[i + n * 3] ) );return 0; } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的CF1473E Minimum Path(拆点+最短路)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。