用线段树维护建图,即把用线段树把每个区间都标号了,Tree1中子节点有到达父节点的单向边,Tree2中父节点有到达子节点的单向边.
每次将源插入Tree1,汇插入Tree2,中间用临时节点相连。那么Tree1中的所用子节点都可以到达,Tree2中的所用子节点。
感觉很有道理啊,以前从来没用用线段树这样维护过建图。分层图最短路没有像BZOJ2763可以直接向先一层连边,因为边已经很多了。
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 #include <vector> 7 #define pa pair<int,int> 8 #define pa3 pair<int,pa> 9 #define mp make_pair 10 #define fi first 11 #define se second 12 #define pb push_back 13 using namespace std; 14 const int Maxn=800010; 15 const int Maxk=12; 16 struct Edge{int to,next,w;}edge[Maxn<<5]; 17 vector<int> P1,P2; 18 priority_queue<pa3,vector<pa3>,greater<pa3> > Q; 19 int n,m,Id1[Maxn],Id2[Maxn],head[Maxn],dis[Maxn][Maxk],cnt,Block; 20 int Kase,v,k; 21 inline void Add(int u,int v,int w) 22 {edge[cnt].to=v;edge[cnt].next=head[u];edge[cnt].w=w;head[u]=cnt++;} 23 inline int Max(int x,int y) {return x>y?x:y;} 24 inline void Get_Int(int &x) 25 { 26 x=0; char ch=getchar(); int f=1; 27 while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} 28 while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} x*=f; 29 } 30 inline void Put_Int(int x) 31 { 32 char ch[20]; int top=0; 33 if (x==0) ch[++top]='0'; 34 while (x) ch[++top]=x%10+'0',x/=10; 35 while (top) putchar(ch[top--]); putchar(' '); 36 } 37 void Build1(int o,int l,int r) 38 { 39 Block=Max(Block,o); 40 if (l==r) {Id1[l]=o; return;} 41 int mid=(l+r)>>1; 42 Build1(o<<1,l,mid),Build1(o<<1|1,mid+1,r); 43 Add(o<<1,o,0),Add(o<<1|1,o,0); 44 } 45 void Build2(int o,int l,int r) 46 { 47 if (l==r) {Id2[l]=Block+o; Add(Id2[l],Id1[l],0);return;} 48 int mid=(l+r)>>1; 49 Build2(o<<1,l,mid),Build2(o<<1|1,mid+1,r); 50 Add(Block+o,Block+(o<<1),0),Add(Block+o,Block+(o<<1|1),0); 51 } 52 void Modify1(int o,int l,int r,int p,int q) 53 { 54 if (l==p && r==q) {P1.pb(o); return;} 55 int mid=(l+r)>>1; 56 if (q<=mid) Modify1(o<<1,l,mid,p,q); 57 if (p>=mid+1) Modify1(o<<1|1,mid+1,r,p,q); 58 if (p<=mid && q>=mid+1) 59 Modify1(o<<1,l,mid,p,mid),Modify1(o<<1|1,mid+1,r,mid+1,q); 60 } 61 void Modify2(int o,int l,int r,int p,int q) 62 { 63 if (l==p && r==q) {P2.pb(o+Block); return;} 64 int mid=(l+r)>>1; 65 if (q<=mid) Modify2(o<<1,l,mid,p,q); 66 if (p>=mid+1) Modify2(o<<1|1,mid+1,r,p,q); 67 if (p<=mid && q>=mid+1) 68 Modify2(o<<1,l,mid,p,mid),Modify2(o<<1|1,mid+1,r,mid+1,q); 69 } 70 71 void Dij() 72 { 73 memset(dis,0x7f,sizeof(dis)); 74 Q.push(mp(0,mp(Id1[1],0))); dis[Id1[1]][0]=0; 75 while (!Q.empty()) 76 { 77 int u=Q.top().se.fi,v=Q.top().se.se; Q.pop(); 78 for (int i=head[u];i!=-1;i=edge[i].next) 79 { 80 if (dis[edge[i].to][v]>dis[u][v]+edge[i].w) 81 { 82 dis[edge[i].to][v]=dis[u][v]+edge[i].w; 83 Q.push(mp(dis[edge[i].to][v],mp(edge[i].to,v))); 84 } 85 if (v<k) 86 { 87 if (dis[edge[i].to][v+1]>dis[u][v]) 88 { 89 dis[edge[i].to][v+1]=dis[u][v]; 90 Q.push(mp(dis[edge[i].to][v+1],mp(edge[i].to,v+1))); 91 } 92 } 93 } 94 } 95 } 96 97 98 int main() 99 { 100 Get_Int(Kase); 101 for (int kase=1;kase<=Kase;kase++) 102 { 103 Get_Int(n),Get_Int(m),Get_Int(k); 104 memset(head,-1,sizeof(head)); Block=0; 105 Build1(1,1,n); Block++; Build2(1,1,n); 106 int tot=(Block<<1)+1,a,b,c,d,w; 107 for (int i=1;i<=m;i++) 108 { 109 Get_Int(a),Get_Int(b),Get_Int(c),Get_Int(d),Get_Int(w); 110 P1.clear(),P2.clear(); 111 Modify1(1,1,n,a,b); 112 Modify2(1,1,n,c,d); 113 tot++; 114 for (int j=0;j<P1.size();j++) Add(P1[j],tot,w); 115 for (int j=0;j<P2.size();j++) Add(tot,P2[j],0); 116 117 118 P1.clear(),P2.clear(); 119 Modify1(1,1,n,c,d); 120 Modify2(1,1,n,a,b); 121 tot++; 122 for (int j=0;j<P1.size();j++) Add(P1[j],tot,w); 123 for (int j=0;j<P2.size();j++) Add(tot,P2[j],0); 124 } 125 } 126 Dij(); 127 if (dis[Id2[n]][k]==0x7fffffff) puts("CreationAugust is a sb!"); else 128 Put_Int(dis[Id2[n]][k]); 129 return 0; 130 }