题目
下水道的主干路由n个节点和\(n-1\)条边所组成,每条边通过它都需要一个时间\(t_i\),这种边是双向的
下水道上有一些塌陷,我们用\((l_1,r_1,l_2,r_2,c)\)来描述,表示从\(l_1\)到\(r_1\)路径上的点,到\(l_2\)和\(r_2\)路径上的任意一个点所需要的时间为\(c\),注意塌陷是单向的
求每一个点到目标节点\(k\)的最快时间
思路
到\(k\)转换\(k\)到每一个点,塌陷反过来建就好了
之后考虑塌陷
直接树链剖分暴力建图即可
代码
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<cstdio>
using namespace std;
void read(int &x)
{
x=0;
int f=1;
char c=getchar();
while('0'>c||c>'9')
{
if(c=='-')
f=-1;
c=getchar();
}
while('0'<=c&&c<='9')
{
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
}
x*=f;
}
void read(long long &x)
{
x=0;
int f=1;
char c=getchar();
while('0'>c||c>'9')
{
if(c=='-')
f=-1;
c=getchar();
}
while('0'<=c&&c<='9')
{
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
}
x*=f;
}
void write(long long x)
{
if(x>9)
write(x/10);
putchar(x%10+'0');
}
struct node
{
#define MAXN 250005
struct node_tre
{
int l;
int r;
}tre[2][MAXN*4];
struct node_g
{
int e;
long long w;
friend bool operator < (const node_g &a,const node_g &b)
{
return a.w>b.w;
}
};
int n,m,s;
int cnt;
vector<node_g> tree[MAXN];
vector<node_g> g[9*MAXN+100005*2];
int id[MAXN];
int wson[MAXN];
int siz[MAXN];
int ori[MAXN];
int dep[MAXN];
int top[MAXN];
int fa[MAXN];
long long dis[9*MAXN+100005*2];
bool vis[9*MAXN+100005*2];
priority_queue<node_g> q;
#undef MAXN
void add_edge(int u,int v,long long w)
{
tree[u].push_back((node_g){v,w});
}
void dfs1(int u,int fa)
{
int maxx=-1;
siz[u]=1;
dep[u]=dep[fa]+1;
for(int i=0;i<tree[u].size();i++)
{
int v=tree[u][i].e;
if(v!=fa)
{
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>maxx)
{
maxx=siz[v];
wson[u]=v;
}
}
}
}
void dfs2(int u,int top_chain)
{
top[u]=top_chain;
id[u]=++cnt;
ori[cnt]=u;
if(wson[u])
dfs2(wson[u],top_chain);
for(int i=0;i<tree[u].size();i++)
{
int v=tree[u][i].e;
if(v!=wson[u]&&dep[v]==dep[u]+1)
{
fa[v]=u;
dfs2(v,v);
}
}
}
void build(int l,int r,int k)
{
tre[0][k].l=tre[1][k].l=l;
tre[0][k].r=tre[1][k].r=r;
if(l==r)
{
g[l].push_back((node_g){n+k,0});
g[5*n+k].push_back((node_g){l,0});
return;
}
g[n+(k<<1)].push_back((node_g){n+k,0});
g[n+(k<<1|1)].push_back((node_g){n+k,0});
g[5*n+k].push_back((node_g){5*n+(k<<1),0});
g[5*n+k].push_back((node_g){5*n+(k<<1|1),0});
int mid=(l+r)>>1;
build(l,mid,k<<1);
build(mid+1,r,k<<1|1);
}
void init()
{
dfs1(1,0);
dfs2(1,1);
build(1,n,1);
for(int i=1;i<=n;i++)
{
for(int j=0;j<tree[i].size();j++)
{
int v=tree[i][j].e;
long long w=tree[i][j].w;
g[id[i]].push_back((node_g){id[v],w});
g[id[v]].push_back((node_g){id[i],w});
}
}
cnt=9*n;
}
void change_tre(int l,int r,int id,int k,int opt)
{
if(l>tre[opt][k].r||tre[opt][k].l>r)
return;
if(l<=tre[opt][k].l&&tre[opt][k].r<=r)
{
if(opt==0)
g[n+k].push_back((node_g){id,0});
else
g[id].push_back((node_g){5*n+k,0});
return;
}
change_tre(l,r,id,k<<1,opt);
change_tre(l,r,id,k<<1|1,opt);
}
void change(int x,int y,int st,int opt)
{
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])
swap(x,y);
change_tre(id[top[y]],id[y],st,1,opt);
y=fa[top[y]];
}
if(dep[x]<dep[y])
swap(x,y);
change_tre(id[y],id[x],st,1,opt);
}
void link(int l1,int r1,int l2,int r2,long long w)
{
change(l1,r1,++cnt,0);
change(l2,r2,++cnt,1);
g[cnt-1].push_back((node_g){cnt,w});
}
void dij()
{
memset(dis,0x3f,sizeof(dis));
q.push((node_g){id[s],0});
dis[id[s]]=0;
while(!q.empty())
{
node_g u=q.top();
q.pop();
if(vis[u.e])
continue;
vis[u.e]=1;
for(int i=0;i<g[u.e].size();i++)
{
int v=g[u.e][i].e;
long long w=g[u.e][i].w;
if(dis[u.e]+w<dis[v])
{
dis[v]=w+dis[u.e];
q.push((node_g){v,dis[v]});
}
}
}
}
void pr()
{
for(int i=1;i<=n;i++)
{
write(dis[id[i]]);
putchar('\n');
}
}
}tre;
int main()
{
read(tre.n);
read(tre.m);
read(tre.s);
for(int i=1,u,v;i<tre.n;i++)
{
long long w;
read(u);
read(v);
read(w);
tre.add_edge(u,v,w);
tre.add_edge(v,u,w);
}
tre.init();
for(int i=1,l1,r1,l2,r2;i<=tre.m;i++)
{
long long w;
read(l1);
read(r1);
read(l2);
read(r2);
read(w);
swap(l1,l2);
swap(r1,r2);
tre.link(l1,r1,l2,r2,w);
}
tre.dij();
tre.pr();
return 0;
}
原文地址:https://www.cnblogs.com/loney-s/p/12237607.html
时间: 2024-10-13 16:20:23