[bzoj3073]Journeys
来源:互联网 发布:infographic制作软件 编辑:程序博客网 时间:2024/06/06 02:02
题目描述
Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路。N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造道路:(a,b),(c,d)表示,对于任意两个国家x,y,如果a<=x<=b,c<=y<=d,那么在xy之间建造一条道路。Seter保证一条道路不会修建两次,也保证不会有一个国家与自己之间有道路。
Seter好不容易建好了所有道路,他现在在位于P号的首都。Seter想知道P号国家到任意一个国家最少需要经过几条道路。当然,Seter保证P号国家能到任意一个国家。
注意:可能有重边
线段树优化
我们朴素想法是把图建出来跑最短路。
直接建图边数爆炸。
尝试数据结构优化连边。
可以建两颗线段树,分别称为A和B。
A和B中同一个节点B向A连边权为0。
A中儿子向父亲连边权为0。
B中父亲向儿子连边权为0。
对于一条边,可以分别在两颗线段树定位对应区间。
建一个新的辅助点,A中都向它连边权为1,它向B中连边权为1。
这样的话,原图联通性没有改变,而且新图上p在A上的叶子走到每个点在A上的叶子的最短路除以2就是原图最短路。
建完图跑Dij+heap
#include<cstdio>#include<algorithm>#include<queue>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;const int maxn=500000+10,maxtot=5*maxn+10,maxm=maxtot*7,inf=1000000000;struct dong{ int x,y; friend bool operator<(dong a,dong b){ return a.y>b.y||a.y==b.y&&a.x<b.x; }} zlt;priority_queue<dong> dl;int h[maxtot],go[maxm],dis[maxm],next[maxm],left[maxtot],right[maxtot],f[maxtot],leaf[maxn],sta[80];bool bz[maxtot];int i,j,k,l,r,t,n,m,p,now,tot,top,root1,root2;int read(){ int x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9'){ if (ch=='-') f=-1; ch=getchar(); } while (ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } return x*f;}void add(int x,int y,int z){ go[++top]=y; dis[top]=z; next[top]=h[x]; h[x]=top;}void build(int &x,int l,int r,int p){ x=++tot; if (l==r){ if (p==1) leaf[l]=x; return; } int mid=(l+r)/2; build(left[x],l,mid,p);build(right[x],mid+1,r,p); if (p==1){ add(left[x],x,0); add(right[x],x,0); } else{ add(x,left[x],0); add(x,right[x],0); }}void connect(int x,int y,int l,int r){ add(y,x,0); if (l==r) return; int mid=(l+r)/2; connect(left[x],left[y],l,mid); connect(right[x],right[y],mid+1,r);}void link(int x,int l,int r,int a,int b,int p){ if (l==a&&r==b){ if (p==1) add(x,tot,1);else add(tot,x,1); return; } int mid=(l+r)/2; if (b<=mid) link(left[x],l,mid,a,b,p); else if (a>mid) link(right[x],mid+1,r,a,b,p); else{ link(left[x],l,mid,a,mid,p); link(right[x],mid+1,r,mid+1,b,p); }}void write(int x){ if (!x){ putchar('0'); putchar('\n'); return; } top=0; while (x){ sta[++top]=x%10; x/=10; } while (top) putchar('0'+sta[top--]); putchar('\n');}int main(){ //freopen("data.in","r",stdin); n=read();m=read();p=read(); build(root1,1,n,1);build(root2,1,n,-1); connect(root1,root2,1,n); fo(i,1,m){ j=read();k=read();l=read();r=read(); ++tot; link(root1,1,n,j,k,1);link(root2,1,n,l,r,-1); swap(j,l);swap(k,r); ++tot; link(root1,1,n,j,k,1);link(root2,1,n,l,r,-1); } t=leaf[p]; f[t]=0; zlt.x=t;zlt.y=0; dl.push(zlt); fo(i,1,tot) if (i!=t){ zlt.x=i;zlt.y=f[i]=inf; dl.push(zlt); } fo(i,1,tot-1){ do{ zlt=dl.top(); dl.pop(); now=zlt.x; }while (bz[now]); bz[now]=1; t=h[now]; while (t){ if (f[now]+dis[t]<f[go[t]]){ f[go[t]]=f[now]+dis[t]; zlt.x=go[t];zlt.y=f[go[t]]; dl.push(zlt); } t=next[t]; } } fo(i,1,n) write(f[leaf[i]]/2);}
0 0
- [bzoj3073]Journeys
- 【PA2011】【BZOJ3073】Journeys
- BZOJ3073:Journeys(线段树)
- 【线段树优化建图+BFS】BZOJ3073(Pa2011)[Journeys]题解
- 【线段树优化建图+最短路】BZOJ3073 [Pa2011]Journeys
- [bzoj3073][Pa2011]Journeys 线段树优化建边的最短路
- bzoj 3073: [Pa2011]Journeys
- 3073: [Pa2011]Journeys|线段树|BFS
- Gym - 100203J Journeys on the Moscow Underground
- [线段树优化建图最短路 bfs] BZOJ 3073 [Pa2011]Journeys
- BZOJ 3073: [Pa2011]Journeys 线段树优化最短路
- bzoj 3073: [Pa2011]Journeys 线段树优化建图+堆优化dij
- BZOJ 3073 [Pa2011]Journeys 最短路 线段树优化建图
- L2-005. 集合相似度
- 解决CentOS下无法发送邮件的问题
- Thinkphp中 IF标签报错
- MATLAB中imshow()显示问题
- 1081. Rational Sum (20)
- [bzoj3073]Journeys
- hjr教程-JSP(六):J2EE项目架构
- Directshow Filter 链接过程
- volitale
- c语言文件初谈
- Java集合---HashMap源码剖析
- hive array、map、struct使用
- Android进程间通信(IPC)机制Binder简要介绍和学习计划
- Shell中的数组及其相关操作