1 条题解
-
0
考虑那个式子实际上就是删掉最大值加上最小值。
把他看成将一条边乘二,一条边删掉,然后发现这个东西恰好满足最短路。
然后直接记录是否乘二,是否删掉,跑分层图最短路就好了。
代码
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<ll,int> Int; const int N=2e5+5; int n,m,id[N][4],vis[N*4]; ll dis[N*4]; vector<Int> e[N*4]; priority_queue<Int,vector<Int>,greater<Int> > q; void add(int x,int y,int z){ e[id[x][0]].emplace_back(id[y][0],z); e[id[y][1]].emplace_back(id[x][1],z); e[id[y][2]].emplace_back(id[x][2],z); e[id[y][3]].emplace_back(id[x][3],z); e[id[x][0]].emplace_back(id[y][1],0); e[id[x][0]].emplace_back(id[y][2],2*z); e[id[x][0]].emplace_back(id[y][3],z); e[id[x][1]].emplace_back(id[y][3],2*z); e[id[x][2]].emplace_back(id[y][3],0); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)id[i][0]=i,id[i][1]=n+i,id[i][2]=2*n+i,id[i][3]=3*n+i; for(int i=1;i<=m;i++){ int x,y;ll z; scanf("%d%d%lld",&x,&y,&z); add(x,y,z),add(y,x,z); } memset(dis,63,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[1]=0; priority_queue<Int,vector<Int>,greater<Int> > q; q.push(make_pair(0,1)); while(!q.empty()){ int x=q.top().second;q.pop(); if(vis[x])continue; vis[x]=1; for(auto i:e[x]){ int y=i.first,z=i.second; if(dis[y]>dis[x]+z){ dis[y]=dis[x]+z; q.push(make_pair(dis[y],y)); } } } for(int i=2;i<=n;i++)printf("%lld ",dis[id[i][3]]); }
- 1
信息
- ID
- 84
- 时间
- 3000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者