BZOJ3073 PA2011Journeys(线段树+bfs)
线段树优化建图裸题。建两棵线段树,一棵表示入一棵表示出。对题中所给的边新建一个虚拟点,将两段区间拆成线段树上对应区间,出线段树中对应区间所表示的点向虚拟点连边权0的边,虚拟点向入线段树中对应区间所表示的点连边权1的边;线段树上的点之间连边权0的边(表示入的由父亲连向儿子,表示出的由儿子连向父亲),表示相同点的叶子节点(由入连向出)之间连边权0的边。01bfs即可。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> #include<queue> using namespace std; #define ll long long #define N 500010 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,m,S,id[2][N],root[2],v[2][100],p[N*10],d[N*10],t,cnt; struct data{int to,nxt,len; }edge[N<<5]; struct data2{int l,r; }tree[2][N<<3]; deque<int> q; void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;} void build(int &k,int l,int r,int p) { k=++cnt; if (l==r) {id[p][l]=k;return;} int mid=l+r>>1; build(tree[p][k].l,l,mid,p); build(tree[p][k].r,mid+1,r,p); if (p==0) addedge(tree[p][k].l,k,0),addedge(tree[p][k].r,k,0); else addedge(k,tree[p][k].l,0),addedge(k,tree[p][k].r,0); } void find(int &k,int l,int r,int x,int y,int p) { if (l==x&&r==y) {v[p][++v[p][0]]=k;return;} int mid=l+r>>1; if (y<=mid) find(tree[p][k].l,l,mid,x,y,p); else if (x>mid) find(tree[p][k].r,mid+1,r,x,y,p); else find(tree[p][k].l,l,mid,x,mid,p),find(tree[p][k].r,mid+1,r,mid+1,y,p); } void bfs(int S) { d[S]=0;q.push_back(S); while (!q.empty()) { int x=q.front();q.pop_front(); for (int i=p[x];i;i=edge[i].nxt) if (d[x]+edge[i].len<d[edge[i].to]) { d[edge[i].to]=d[x]+edge[i].len; if (edge[i].len) q.push_back(edge[i].to); else q.push_front(edge[i].to); } } } int main() { #ifndef ONLINE_JUDGE freopen("bzoj3073.in","r",stdin); freopen("bzoj3073.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(),m=read(),S=read(); build(root[0],1,n,0); build(root[1],1,n,1); for (int i=1;i<=m;i++) { int a=read(),b=read(),c=read(),d=read(); v[0][0]=v[1][0]=0;cnt++; find(root[0],1,n,a,b,0); for (int x=1;x<=v[0][0];x++) addedge(v[0][x],cnt,0); find(root[1],1,n,c,d,1); for (int x=1;x<=v[1][0];x++) addedge(cnt,v[1][x],1); v[0][0]=v[1][0]=0;cnt++; find(root[0],1,n,c,d,0); for (int x=1;x<=v[0][0];x++) addedge(v[0][x],cnt,0); find(root[1],1,n,a,b,1); for (int x=1;x<=v[1][0];x++) addedge(cnt,v[1][x],1); } for (int i=1;i<=n;i++) addedge(id[1][i],id[0][i],0); memset(d,42,sizeof(d));bfs(id[0][S]); for (int i=1;i<=n;i++) printf("%d\n",d[id[0][i]]); return 0; }