P2934 解题报告
前言
某模拟赛中打到的,场上切了,感觉还挺有趣的?
思路分析
这个题目操作是封住最后一条边,而给的限制条件也很奇怪:特别地,保证
最后一条边不好考虑,我们考虑从限制条件下手。
这个限制条件告诉我们,如果我们只保留最短路会走过的边,那么剩下的就是一颗树。
因为路径唯一,所以最后一条边也唯一,推一下也就是对于每个点他的父亲唯一,那么显然就是一个树的形状。
考虑用 dijkstra 求出最短路的同时处理出最短路树。
这样第一步就完成了,我们有了一颗最短路树,接下来按照题目的要求要封住最后一条边球最短路。
显然大力的方法会 T 飞,考虑优化。
考虑我们已经求出
假设我们要求的点为
因为对于每条边,他的
显然的是考虑先用
然后考虑更新过程如何做到让一个点最多被更新一次。
想到并查集,对于一个点,更新他后把他合进父亲中即可。
显然,这题树剖也可以做,做法类似于其结合 MST 时的做法,在此不多赘述,读者可以自行思考一二(其实是我考场懒得码就上并查集了)。
Tips:题目有无解,无解输出
代码
#include <bits/stdc++.h>
#define mid ((l+r)>>1)
#define int long long
using namespace std;
const int N=200010,p=338651,INF=0x3f3f3f3f3f3f3f3f;
struct edge{int v,w,id;};
struct node{int u,v,w;};
int n,m,cnt;bool mp[N];
int bcu[N<<1],bcv[N<<1],bcw[N<<1],a[N],d[N],ans[N],fa[N],dep[N];
vector<int>e[N];vector<edge>g[N];vector<node>eg;
namespace Fast_IO
{
static char buf[1000000],*paa=buf,*pd=buf;
#define getchar() paa==pd&&(pd=(paa=buf)+fread(buf,1,1000000,stdin),paa==pd)?EOF:*paa++
inline int read()
{
int x(0),t(1);char fc(getchar());
while(!isdigit(fc)){if(fc=='-') t=-1;fc=getchar();}
while(isdigit(fc)) x=(x<<1)+(x<<3)+(fc^48),fc=getchar();
return x*t;
}
inline void print(int x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) print(x/10);
putchar(x%10+'0');
}
}
using namespace Fast_IO;
void dij()
{
priority_queue<pair<int,int>>q;q.push(make_pair(0,1));memset(d,0x3f,sizeof d);d[1]=0;
while(!q.empty())
{
int u=q.top().second;if(d[u]<-q.top().first){q.pop();continue;}q.pop();dep[u]=dep[fa[u]]+1;
for(auto to:g[u])
{
int v=to.v,w=to.w;
if(d[u]+w<d[v])
{
d[v]=d[u]+w;mp[a[v]]=0;
q.push(make_pair(-d[v],v));fa[v]=u;
}
}
}
}
inline void add(int u,int v) { e[u].emplace_back(v),e[v].emplace_back(u); }
struct DSU
{
vector<int> h;
inline void init(int n){h=vector<int>(n+10);for(int i=1;i<=n;i++) h[i]=i;}
inline int find(int x){return h[x]==x?x:h[x]=find(h[x]);}
}f;
bool cmp(node x,node y){return d[x.u]+d[x.v]+x.w<d[y.u]+d[y.v]+y.w;}
signed main()
{
n=read(),m=read();
for(int i=1,u,v,w;i<=m;i++) bcu[i]=u=read(),bcv[i]=v=read(),bcw[i]=w=read(),g[u].emplace_back((edge){v,w,i}),g[v].emplace_back((edge){u,w,i});
dij();memset(ans,-1,sizeof ans);
for(int i=1;i<=m;i++) if(fa[bcu[i]]!=bcv[i]&&fa[bcv[i]]!=bcu[i]) eg.emplace_back((node){bcu[i],bcv[i],bcw[i]});
sort(eg.begin(),eg.end(),cmp);f.init(n);
for(auto i:eg)
{
int u=f.find(i.u),v=f.find(i.v);
while(u!=v)
{
if(dep[u]<dep[v]) swap(u,v);
ans[u]=d[i.u]+d[i.v]+i.w-d[u];
f.h[u]=fa[u];u=f.find(u);
}
}
for(int i=2;i<=n;i++) print(ans[i]),puts("");
return 0;
}