E. Paired Payment 分层图最短路
题目大意:
给你 n 个点,m条边的图,每次至少走2步,权值即为两步经过的边的权值之和的平方,问从1点出发到达 (t) 点的最短距离。
题解:
定义 (dp[i][x]) 表示到第 (i) 个节点,上一条边的权值是 (j) 的最优解。
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
int cnt,to[maxn*2],nxt[maxn*2],head[maxn],w[maxn*2];
void add(int u,int v,int c){
++cnt,to[cnt] = v,w[cnt] = c,nxt[cnt] = head[u],head[u] = cnt;
}
int dis[maxn][55];
bool vis[maxn][55];
struct node{
int u,pre,d;
node(int u=0,int pre=0,ll d=0):u(u),pre(pre),d(d){}
bool operator<(const node &a)const{
return a.d<d;
}
};
priority_queue<node>que;
void dij(int s){
memset(vis,0,sizeof(vis));
memset(dis,inf,sizeof(dis));
dis[s][0] = 0;
que.push(node(s,0,0));
while(!que.empty()){
node x = que.top();que.pop();
int u = x.u,pre = x.pre;
// printf("u = %d pre = %d dis = %lld
",u,pre,x.d);
if(vis[u][pre]) continue;
vis[u][pre] = true;
for(int i=head[u];i;i=nxt[i]){
int v = to[i],c = w[i];
if(pre==0){
if(dis[v][c]>dis[u][pre]){
dis[v][c] = dis[u][pre];
que.push(node(v,c,dis[v][c]));
}
}
else{
int val = (c+pre)*(c+pre);
if(dis[v][0]>dis[u][pre]+val){
dis[v][0] = dis[u][pre] + val;
que.push(node(v,0,dis[v][0]));
}
}
}
}
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
add(u,v,c);
add(v,u,c);
}
dij(1);
for(int i=1;i<=n;i++){
if(dis[i][0]>=inf) printf("-1");
else printf("%d",dis[i][0]);
if(i==n) printf("
");
else printf(" ");
}
return 0;
}