LGP3783题解

前排提醒:多测不清空的你再强大,考场上也是假的!

题意有些复杂所以我在这里说一下。。。

给定一张图 \(G\) 和一棵树 \(T\),图上每条边有一个边权 \(w\) 和树上的一个节点 \(u\),经过一条边 \(a\) 后再经过一条边 \(b\) 的代价为 \(b.w+LCA(a.u,b.u)\),求 \(1\) 节点到每个节点的最短路。经过第一条边的代价仅为 \(a.w\)

首先容易发现信息都是给在边上的,甚至需要计算边对边的信息。所以在点上跑最短路是没有前途的,要把边建成一个点,然后对这些点跑最短路。

再转化成原图上的最短路很简单,把最短路塞到出点上去就行了。

枚举中转点,我们要将入边对应的点连接到出边上面去。

我们将入边和出边在 \(T\) 上的点拉出来建一颗虚树。

对于每个节点,我们开两个在需要跑最短路的图上的节点 \(q\)\(p\)。子树内的入边连接 \(q\)\(p\) 连接子树内的出边。

然后从一条边回溯的时候,令 \(q\) 连接 \(p\) 即可,边权为该节点的深度。要合并 \(q\)\(p\) 也很简单。

然后就做完了。复杂度 \(O(\sum m\log n)\)

#include<algorithm>
#include<cstdio>
#include<vector>
#include<cctype>
typedef long long ll;
const int M=2e5+5;
int T,n,m,k,ege,dfc,h[M],f[M],d[M],dfn[M],siz[M],son[M],top[M];ll ans[M];
int tp,stk[M];int q[M],p[M];int len,t[M];int V[M];
struct Graph{
	int G,tot,ege,h[M*10],zkw[M*10<<2];ll d[M*10],ans[M*10];bool vis[M*10];
	struct Edge{
		int v,w,nx;
	}e[M*30];
	inline int nnd(){
		++tot;h[tot]=d[tot]=ans[tot]=vis[tot]=0;return tot;
	}
	inline void Add(const int&u,const int&v,const int&w){
		e[++ege]=(Edge){v,w,h[u]};h[u]=ege;
	}
	inline void Mdf(int u,const ll&V){
		for(d[u]=V,u+=G;u>>=1;zkw[u]=zkw[u<<1|(d[zkw[u<<1|1]]<d[zkw[u<<1]])]);
	}
	inline void Dijkstra(){
		for(G=1;G<=tot+1;G<<=1);for(int i=0;i<=tot;++i)d[zkw[i+G]=i]=1e18,vis[i]=false;
		for(int u=G-1;u;--u)zkw[u]=zkw[u<<1|(d[zkw[u<<1|1]]<d[zkw[u<<1]])];Mdf(m+1,0);
		while(zkw[1]){
			const int u=zkw[1];ans[u]=d[u];Mdf(u,2e18);vis[u]=true;
			for(int v,&E=h[u];E;E=e[E].nx)if(v=e[E].v,!vis[v]&&ans[u]+e[E].w<d[v])Mdf(v,ans[u]+e[E].w);
		}
		for(int i=1;i<=tot;++i)h[i]=0;for(int i=1;i<=tot+G;++i)zkw[i]=0;
		for(int i=1;i<=m;++i)if(ans[i]<::ans[V[i]])::ans[V[i]]=ans[i];
		tot=ege=0;
	}
}G;
struct Edge{
	int v,nx;
}e[M];
struct edge{
	int w,u,id;
};std::vector<edge>in[M],out[M];
inline void Add(const int&u,const int&v){
	e[++ege]=(Edge){v,h[u]};h[u]=ege;
}
inline void DFS1(const int&u){
	d[u]=d[f[u]]+1;siz[u]=1;
	for(int v,E=h[u];E;E=e[E].nx)if((v=e[E].v)^f[u])f[v]=u,DFS1(v),siz[v]>siz[son[u]]&&(son[u]=v),siz[u]+=siz[v];
}
inline void DFS2(const int&u,const int&tp){
	top[u]=tp;dfn[u]=++dfc;if(!son[u])return;DFS2(son[u],tp);
	for(int E=h[u];E;E=e[E].nx)if(e[E].v^f[u]&&e[E].v^son[u])DFS2(e[E].v,e[E].v);
}
inline int LCA(int u,int v){
	while(top[u]^top[v])d[top[u]]>d[top[v]]?u=f[top[u]]:v=f[top[v]];return d[u]>d[v]?v:u;
}
inline void Insert(const int&u){
	if(!tp)return void(stk[tp=1]=u);
	const int&v=LCA(u,stk[tp]);while(tp>1&&d[v]<d[stk[tp-1]])Add(stk[tp-1],stk[tp]),--tp;
	if(stk[tp]^v)Add(v,stk[tp--]);if(v^stk[tp])stk[++tp]=v;if(u^stk[tp])stk[++tp]=u;
}
inline void Solve(const int&u){
	if(q[u]&&p[u])G.Add(q[u],p[u],d[u]);
	for(int v,&E=h[u];E;E=e[E].nx){
		Solve(v=e[E].v);if(q[u]&&p[v])G.Add(q[u],p[v],d[u]);if(q[v]&&p[u])G.Add(q[v],p[u],d[u]);
		if(q[v])q[u]?G.Add(q[u],G.nnd(),0),G.Add(q[v],q[u]=G.tot,0),0:q[u]=q[v];
		if(p[v])p[u]?G.Add(G.nnd(),p[u],0),G.Add(p[u]=G.tot,p[v],0),0:p[u]=p[v];
		q[v]=p[v]=0;
	}
}
inline void work(const int&u){
	for(edge&E:in[u])t[++len]=E.u;for(edge&E:out[u])t[++len]=E.u;
	std::sort(t+1,t+len+1,[](const int&a,const int&b){return dfn[a]<dfn[b];});len=std::unique(t+1,t+len+1)-t-1;
	for(edge&E:in[u])!q[E.u]&&(q[E.u]=G.nnd()),G.Add(E.id,q[E.u],0);
	for(edge&E:out[u])!p[E.u]&&(p[E.u]=G.nnd()),G.Add(p[E.u],E.id,E.w);
	for(int i=1;i<=len;++i)Insert(t[i]);while(tp>1)Add(stk[tp-1],stk[tp]),--tp;
	Solve(stk[tp]);q[stk[tp]]=p[stk[tp]]=0;len=tp=0;
}
inline int read(){
	int n(0);char s;while(!isdigit(s=getchar()));while(n=n*10+(s&15),isdigit(s=getchar()));return n;
}
signed main(){
	T=read();d[0]=-1;
	while(T--){
		n=read();m=read();k=read();G.tot=m;
		for(int i=1;i<=n;++i)ans[i]=1e18;
		for(int u,v,t,p,i=1;i<=m;++i){
			u=read();v=read();t=read();p=read();V[i]=v;
			in[v].push_back((edge){t,p,i});out[u].push_back((edge){t,p,i});
		}
		for(int u,v,i=1;i<k;++i)u=read(),v=read(),read(),Add(u,v);DFS1(1);DFS2(1,1);for(int i=1;i<=k;++i)h[i]=0;
		G.nnd();for(edge&E:out[1])G.Add(G.tot,E.id,E.w);
		for(int u=1;u<=n;++u)if(!in[u].empty()&&!out[u].empty())work(u);
		G.Dijkstra();for(int i=2;i<=n;++i)printf("%lld\n",ans[i]);
		for(int i=1;i<=k;++i)h[i]=f[i]=d[i]=dfn[i]=siz[i]=son[i]=top[i]=0;
		for(int i=1;i<=n;++i)ans[i]=0,std::vector<edge>().swap(in[i]),std::vector<edge>().swap(out[i]);
		for(int i=1;i<=m;++i)V[i]=0;dfc=ege=0;
	}
}
posted @ 2022-06-16 10:21  Prean  阅读(22)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};