codeforces 786B legacy 线段树建图
http://www.cnblogs.com/jianrenfang/p/6622404.html
会长的代码很朴实,很平易近人。就是区间最短路。
#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int>pii; typedef long long LL; const int N=6e6+5; const int mod=1e9+7; int n,m,s,cnt,idl[N<<1],idr[N<<1]; bool vis[N]; LL d[N]; vector<pii>edg[N]; void buildl(int rt,int l,int r)//向上走的一棵树 { idl[rt]=++cnt; if(l==r)return ; int m=l+r>>1; buildl(rt<<1,l,m); buildl(rt<<1|1,m+1,r); edg[idl[rt<<1]].push_back(make_pair(idl[rt],0)); edg[idl[rt<<1|1]].push_back(make_pair(idl[rt],0)); } void buildr(int rt,int l,int r)//向下走的一棵树 { idr[rt]=++cnt; if(l==r)return ; int m=l+r>>1; buildr(rt<<1,l,m); buildr(rt<<1|1,m+1,r); edg[idr[rt]].push_back(make_pair(idr[rt<<1],0)); edg[idr[rt]].push_back(make_pair(idr[rt<<1|1],0)); } void pre(int rt,int l,int r)//连成回路 { if(l==r) { edg[l].push_back(make_pair(idl[rt],0)); edg[idr[rt]].push_back(make_pair(l,0)); return; } int m=l+r>>1; pre(rt<<1,l,m); pre(rt<<1|1,m+1,r); } void addl(int rt,int l,int r,int L,int R,int w)//上走的树连虚点 { if(L<=l&&r<=R) { edg[idl[rt]].push_back(make_pair(cnt,w)); return; } int mid=(l+r)/2; if(L<=mid)addl(rt*2,l,mid,L,R,w); if(R>mid)addl(rt*2+1,mid+1,r,L,R,w); } void addr(int rt,int l,int r,int L,int R)//虚点连向下走的树 { if(L<=l&&r<=R) { edg[cnt].push_back(make_pair(idr[rt],0)); return; } int mid=(l+r)/2; if(L<=mid)addr(rt*2,l,mid,L,R); if(R>mid)addr(rt*2+1,mid+1,r,L,R); } struct man { int v; LL w; bool operator<(const man &e)const { return w>e.w; } }; priority_queue<man>q; void dij(int s) { for(int i=0; i<=cnt; i++)d[i]=-1,vis[i]=0; d[s]=0; q.push(man{s,0}); while(!q.empty()) { int u=q.top().v; q.pop(); if(vis[u])continue; vis[u]=1; for(int i=0; i<edg[u].size(); ++i) { int v=edg[u][i].first,w=edg[u][i].second; if(!vis[v]&&(d[v]==-1||d[v]>d[u]+w)) { d[v]=d[u]+w; q.push(man{v,d[v]}); } } } } int main() { int w; scanf("%d%d%d",&n,&m,&s); cnt=n;//前n个点预留出来 buildl(1,1,n); buildr(1,1,n); pre(1,1,n); while(m--) { ++cnt;//中间一个过渡节点好写 int op,l,r,x,y; scanf("%d",&op); if(op==1) { scanf("%d%d%d",&x,&y,&w); addl(1,1,n,x,x,w); addr(1,1,n,y,y); } else if(op==2) { scanf("%d%d%d%d",&x,&l,&r,&w); addl(1,1,n,x,x,w); addr(1,1,n,l,r); } else { scanf("%d%d%d%d",&x,&l,&r,&w); addl(1,1,n,l,r,w); addr(1,1,n,x,x); } } dij(s); for(int i=1; i<=n; i++)printf("%lld%c",d[i],i==n?'\n':' '); return 0; }