CF786B 线段树优化建图
题目大意
有个星球,编号,可以建立下面三种边(q次):
- 星球到编号间的星球每一个建立一条边
- 编号间的每一个星球到星球建立一条边
- 星球到星球建立一条边
给定起点,问起点到其他个点的最短距离。
求最短路并不难,问题在于边数过多。
由于建立的边都是从某个点到一定的区间范围内的点,可以考虑给区间家里一个点,这样就减少了边的数量。这个就是线段树优化建边。
方法:
- 给区间建立两颗线段树。一棵树叫出树,另一棵叫入树。出树内建立从父节点到左右子节点的有向边。入树内建立从左右孩子到父节点的有向边。
- 用无向边把出树和入树的叶节点按编号对应连起来。
- 剩余要建的边;(1)如果是单点相连,直接对入树中对应的点到出树中对应的点建边(2)如果是区间建边,则应用线段树把区间分解到对应的线段树中的点,从入树到出树建边。
有些代码中把入树和出树的叶子节点设为同一点,这样就不用建立无向边了。
注意建图后图中的点数和边数!!!
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int n,qq,s;
int cnt,lc[maxn*3],rc[maxn*3];
int rootin,rootout;
struct edge
{
int u,v,w,nxt;
}e[maxn*20];
int head[maxn*3],js;
void addage(int u,int v,int w)
{
e[++js].v=v;e[js].u=u;e[js].w=w;
e[js].nxt=head[u];head[u]=js;
}
void buildin(int &cur,int l,int r)
{
if(l==r)
{
cur=l;
return ;
}
cur=++cnt;
int mid=(l+r)>>1;
buildin(lc[cur],l,mid);
buildin(rc[cur],mid+1,r);
addage(lc[cur],cur,0);
addage(rc[cur],cur,0);
}
void buildout(int &cur,int l,int r)
{
if(l==r)
{
cur=l;
return ;
}
cur=++cnt;
int mid=(l+r)>>1;
buildout(lc[cur],l,mid);
buildout(rc[cur],mid+1,r);
addage(cur,lc[cur],0);
addage(cur,rc[cur],0);
}
void updat(int root,int l,int r,int ql,int qr,int u,int w,int opt)
{
if(ql<=l&&r<=qr)
{
if(opt==2)addage(u,root,w);
else addage(root,u,w);
return ;
}
int mid=(l+r)>>1;
if(ql<=mid)updat(lc[root],l,mid,ql,qr,u,w,opt);
if(mid<qr)updat(rc[root],mid+1,r,ql,qr,u,w,opt);
}
long long dis[maxn*3];
queue<int>q;
bool inq[maxn*3];
void spfa(int s)
{
memset(dis,0x3f,sizeof dis);
q.push(s);inq[s]=1;dis[s]=0;
while(!q.empty())
{
int u=q.front();
q.pop();inq[u]=0;
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].v;
if(dis[v]>dis[u]+e[i].w)
{
dis[v]=dis[u]+e[i].w;
if(!inq[v])
{
q.push(v);
inq[v]=1;
}
}
}
}
}
int main()
{
scanf("%d%d%d",&n,&qq,&s);
cnt=n;
buildin(rootin,1,n);
buildout(rootout,1,n);
while(qq--)
{
int opt,u,l,r,w;
scanf("%d",&opt);
if(opt==1)
{
scanf("%d%d%d",&u,&l,&w);
addage(u,l,w);
}
else
{
scanf("%d%d%d%d",&u,&l,&r,&w);
updat(opt==2?rootout:rootin,1,n,l,r,u,w,opt);
}
}
spfa(s);
for(int i=1;i<=n;++i)printf("%lld ",dis[i]==0x3f3f3f3f3f3f3f3f?-1:dis[i]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!