一个观察式子,得出结论的题
题目大意:
你需要求出,从 1 1 1~ i i i, 2 ≤ i ≤ n {2\le i \le n} 2≤i≤n的这个权值为:路径总和-路径边权最大值+路径边权最小值
的 最短路
题目思路:
看到从 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;
}
/***
***/