1. 程式人生 > >BZOJ3073 PA2011Journeys(線段樹+bfs)

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; }