第一次看到用最短路树来解题,一下针对这种某些边不能选,次优值之类的最短路除了A*之外的套路.
往往可以求全局,在线可以用LCT来维护
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
const int M = N * 2;
int fir[N] , ne[M] , to[M] , cnt, dis[N] , hu[N] , x , y , z, C[M] , pre[N] , n , m , fa[N] , st[N][26] , dep[N];
bool vis[N];
void add(int x , int y , int z) {
ne[++ cnt] = fir[x]; fir[x] = cnt; to[cnt] = y; C[cnt] = z;
}
void link(int x , int y , int z) {
add(x , y , z);
// cerr << cnt <<" adasd" << endl;
add(y , x , z);
// cerr << cnt <<" adasd" << endl;
}
struct NODE {
int val , id , Pre;
friend bool operator < (NODE xxx , NODE yyy) {
return xxx.val > yyy.val;
}
}tmp , ind;
priority_queue<NODE>q;
#define Foreachson(i , x) for(int i = fir[x];i;i = ne[i])
vector<int>G[N];
void dfs(int x , int f) {
dep[x] = dep[f] + 1; pre[x] = f;
st[x][0] = f; for(int i = 1;i < 21;i ++) st[x][i] = st[st[x][i - 1]][i - 1];
for(int i = 0;i < (int) G[x].size();i ++) {
dfs(G[x][i] , x);
}
}
int getf(int x) {
return (x == fa[x]) ? x : (fa[x] = getf(fa[x]));
}
struct push {
int x , y , val;
friend bool operator < (push xxx , push yyy) {
return xxx.val < yyy.val;
}
}P[N];
int LCA(int x , int y) {
if(dep[x] > dep[y]) swap(x , y);
for(int i = 20;i >= 0;i --) if(dep[st[y][i]] >= dep[x]) y = st[y][i];
if(x == y) return x;
for(int i = 20;i >= 0;i --) if(st[x][i] != st[y][i]) x = st[x][i] , y = st[y][i];
return st[x][0];
}
int main(void) {
// freopen("data.txt" , "r" , stdin);
// freopen("myout.txt" ,"w" , stdout);
scanf("%d%d" , &n , &m); cnt ++;
for(int i = 1;i <= m;i ++) {
scanf("%d%d%d" , &x , &y , &z); link(x , y , z);
}
memset(hu , 127 , sizeof(hu));
q.push((NODE){0 , 1 , 0});
while(!q.empty()) {
while(!q.empty() && vis[q.top().id]) q.pop();
if(q.empty()) break;
ind = q.top(); q.pop();
vis[ind.id] = 1; dis[ind.id] = ind.val; pre[ind.id] = ind.Pre;
Foreachson(i , ind.id) {
int V = to[i]; if(vis[V]) continue;
q.push((NODE){ind.val + C[i] , V , ind.id});
}
}
for(int i = 1;i <= n;i ++) fa[i] = i;
for(int i = 1;i <= n;i ++) G[pre[i]].push_back(i);
dfs(1 , 0);
int tot = 0;
for(int i = 2;i <= cnt;i += 2) {
int u = to[i] , v = to[i ^ 1] , w = C[i];
if(pre[u] == v || pre[v] == u) continue;
P[++ tot].x = u; P[tot].y = v; P[tot].val = dis[u] + dis[v] + C[i];
}
sort(P + 1 , P + tot + 1);
for(int i = 1;i <= tot;i ++) {
if(getf(P[i].x) == getf(P[i].y)) continue;
int fx = getf(P[i].x) , fy = getf(P[i].y);
int lca = getf(LCA(fx , fy));
while(fx != lca) {
hu[fx] = P[i].val - dis[fx];
fa[fx] = pre[fx]; fx = getf(fx);
}
while(fy != lca) {
hu[fy] = P[i].val - dis[fy];
fa[fy] = pre[fy]; fy = getf(fy);
}
}
for(int i = 2;i <= n;i ++) {
if(hu[i] > 4e8) puts("-1");
else printf("%d\n" , hu[i]);
}
}
1513

被折叠的 条评论
为什么被折叠?



