【Codeforces 1473E】Minimum Path | 分层最短路

一个观察式子,得出结论的题

题目大意:

你需要求出,从 1 1 1~ i i i 2 ≤ i ≤ n {2\le i \le n} 2in的这个权值为:路径总和-路径边权最大值+路径边权最小值 的 最短路

题目思路:

看到从 1 1 1到各个点的最短路,那么必然考虑最短路问题。

但是这个问题不太好维护,因为无法同时既维护最大值,又维护最小值。

所以转换一下,把题目要求的式子,理解为:在一条路径上使得一条边的权值消失,还有一条边的权值* 2 2 2。因为要求最小,那么必然是最大边权消失,最小边权* 2 2 2。所以刚好符合题目要求的条件。

所以就可以分层建图了,但是卡在了直接分层建图上,很显然只有一条边的时候分层图答案是不对的,而且还有不能够去重。

所以这时候考虑一下状压,增加两维状态: 一维代表是否执行了消失边的操作,另一维代表是否执行了* 2 2 2的操作。

然后直接在这上面跑个三维最短路即可。

放一下不加堆优化的代码…(被hack了再更)

Code:

/*** keep hungry and calm CoolGuang!  ***/
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define dl(x) printf("%lld\n",x);
#define di(x) printf("%d\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e17+7;
const ll maxn = 1e6+700;
const ll mod= 1e9+7;
const ll up = 1e13;
const double eps = 1e-9;
const double PI = acos(-1);
template<typename T>inline void read(T &a){
    
    char c=getchar();T x=0,f=1;while(!isdigit(c)){
    
    if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){
    
    x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
ll num[maxn];
struct node{
    
    
	int e,next;
	ll w;
}edge[maxn];
int head[maxn];
int cnt = 0;
void addedge(int u,int v,int w){
    
    
	edge[cnt] = node{
    
    v,head[u],w};
	head[u] = cnt++;
}
struct N{
    
    
	int u,x,y;
};
ll dis[maxn][2][2];
int vis[maxn][2][2];
void bfs(){
    
    
	queue<N>q;
	
	dis[1][0][0] = 0;
	vis[1][0][0] = 1;
	q.push(N{
    
    1,0,0});
	while(!q.empty()){
    
    
		N u = q.front();q.pop();
		int id = u.u,x = u.x,y = u.y;
		vis[id][x][y] = 0;

		for(int i=head[id];~i;i=edge[i].next){
    
    
			int e = edge[i].e;
			ll w = edge[i].w;
			///debug(e)
			//debug(dis[e][x][y]);
			//debug(dis[e][x][1]);

			if(dis[e][x][y] > dis[id][x][y] + w){
    
    
				dis[e][x][y] = dis[id][x][y] + w;
				if(!vis[e][x][y]){
    
    
					q.push(N{
    
    e,x,y});
					vis[e][x][y] = 1;
				}
			}
			if(x == 0){
    
    
				if(dis[e][1][y] > dis[id][x][y]){
    
    
					dis[e][1][y] = dis[id][x][y];
					if(!vis[e][1][y]){
    
    
						q.push(N{
    
    e,1,y});
						vis[e][1][y] = 1;
					}
				}
			}
			if(y == 0){
    
    
				if(dis[e][x][1] > dis[id][x][y] + 2*w){
    
    
					dis[e][x][1] = dis[id][x][y] + 2*w;
					if(!vis[e][x][1]){
    
    
						vis[e][x][1] = 1;
						q.push(N{
    
    e,x,1});
					}
				}
			}
		}
	}
}
int main(){
    
    
	memset(head,-1,sizeof(head));

	read(n);read(m);
	for(int i=1;i<=n;i++)
		for(int k=0;k<2;k++)
			for(int j=0;j<2;j++)
				dis[i][k][j] = INF;
	for(int i=1;i<=m;i++){
    
    
		int x,y,w;
		read(x);read(y);read(w);
		if(x>y) swap(x,y); 
		if(x==1) dis[y][1][1] = w;
		addedge(x,y,w);
		addedge(y,x,w);
	}
	bfs();
	for(int i=2;i<=n;i++) printf("%lld ",dis[i][1][1]);
	printf("\n");
	return 0;
}
/***
***/

猜你喜欢

转载自blog.csdn.net/qq_43857314/article/details/112646144