1 条题解
-
0

// 最短路径树+并查集 Dijkstra 算法 O(MlogN) #include<bits/stdc++.h> #define ll long long #define pli pair<ll,int> using namespace std; const int N=100005; vector<pli> e[N]; int n,m; int pa[N],dep[N]; ll d[N]; void dijkstra(){ memset(d,0x3f,sizeof d); d[1]=0; priority_queue<pli,vector<pli>,greater<pli> > q; q.push({0,1}); while(!q.empty()){ auto [dd,u]=q.top(); q.pop(); if(dd!=d[u])continue; for(auto [w,v]:e[u]){ if(d[v]>d[u]+w){ d[v]=d[u]+w; pa[v]=u; //记录父节点 dep[v]=dep[u]+1; //记录深度 q.push({d[v],v}); } } } } struct node{int u,v; ll d;}nt[N<<1]; int cnt,fa[N]; ll ans[N]; int find(int u){ return (u==fa[u])?u:(fa[u]=find(fa[u])); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int a,b; ll t; scanf("%d%d%lld",&a,&b,&t); e[a].push_back({t,b}); e[b].push_back({t,a}); } dijkstra(); for(int u=1;u<=n;u++){ ans[u]=-1; fa[u]=u; //并查集初值 for(auto [w,v]:e[u])if(pa[v]!=u&&pa[u]!=v&&u<v) nt[++cnt]={u,v,d[u]+d[v]+w}; //记录非树边 } sort(nt+1,nt+cnt+1,[](node a,node b){return a.d<b.d;}); for(int i=1;i<=cnt;i++){ //枚举非树边 int u=nt[i].u, v=nt[i].v; ll dd=nt[i].d; //取出端点和距离 u=find(u),v=find(v); //找出端点的根 while(u!=v){ //都爬到lca结束 if(dep[u]<dep[v])swap(u,v); //保证u点深 ans[u]=dd-d[u]; //更新u点答案 fa[u]=pa[u]; //u指向它的父亲 u=find(u); //找出u点的根 } } for(int i=2;i<=n;i++)printf("%lld\n",ans[i]); }
- 1
信息
- ID
- 836
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 4
- 标签
- 递交数
- 23
- 已通过
- 15
- 上传者