题目大意:
两点间最短路的定义变成: 所 有 的 边 之 和 − m a x + m i n 所有的边之和-max+min 所有的边之和−max+min
解题思路:
这里很明显就是变成了最短路的时时候就是把路径上边权最小值乘2,然后把最大值去掉?
相当于免费?
是不是很像分层图?
就是你有两次机会:1.你可以把一条路径上的边权变成0。2.是把边权翻倍
为什么跑分层图最短路就是答案呢?
因为根据最短路的性质肯定是去大边,翻倍小边
我们一共有4种状态:
1.两个机会都没用
2.用了第一个条件,第二个没用
3.用了第二个条件,第一个没用
4.两个都用了
那么直接4个状态这样是不是就可以了呢?
肯定是不行的
因为可能两点间的最短路只有一条边??
那么你这个分层图要到4至少要两条边??
那么怎么办?
第一层和第4层再连一条边
AC code
#include <bits/stdc++.h>
#define mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define log2(a) log(a)/log(2)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define LLF 0x3f3f3f3f3f3f3f3f
#define f first
#define s second
#define endl '\n'
using namespace std;
const int N = 2e6 + 10, mod = 1e9 + 9;
const int maxn = 200010;
const long double eps = 1e-5;
const int EPS = 500 * 500;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,int> PII;
typedef pair<ll,ll> PLL;
typedef pair<double,double> PDD;
template<typename T> void read(T &x) {
x = 0;char ch = getchar();ll f = 1;
while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args) {
read(first);
read(args...);
}
struct node {
int nxt, to, val;
}edge[maxn*20];
int head[maxn<<2], cnt;
int n, m;
inline void add(int from, int to, int val) {
edge[cnt] = {head[from],to,val};
head[from] = cnt ++;
}
priority_queue<PII, vector<PII>, greater<PII> > q;
ll dist[maxn<<2];
bool vis[maxn<<2];
inline void dij() {
ms(dist,LLF);
dist[1] = 0;
q.push({0,1});
while(!q.empty()) {
auto top = q.top();
q.pop();
if(vis[top.second]) continue;
vis[top.second] = 1;
for(int i = head[top.second]; ~i; i = edge[i].nxt) {
int to = edge[i].to;
if(dist[to] > dist[top.second] + edge[i].val) {
dist[to] = dist[top.second] + edge[i].val;
q.push({dist[to],to});
}
}
}
}
int main() {
IOS;
ms(head,-1);
cin >> n >> m;
for(int i = 1; i <= m; ++ i) {
int u, v, w;
cin >> u >> v >> w;
for(int j = 0; j <= 3; j ++) add(u+j*n,v+j*n,w),add(v+j*n,u+j*n,w);
add(u,v+3*n,w);
add(v,u+3*n,w);
add(u,v+n,2*w);
add(v,u+n,2*w);
add(u,v+2*n,0);
add(v,u+2*n,0);
add(u+n,v+3*n,0);
add(v+n,u+3*n,0);
add(u+2*n,v+3*n,2*w);
add(v+2*n,u+3*n,2*w);
}
dij();
for(int i = 2; i <= n; ++ i) cout << dist[i+3*n] << " ";
}