HDU 5669 线段树优化建图+分层图最短路

用线段树维护建图,即把用线段树把每个区间都标号了,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 }
把标答代码改成Dij系列..
原文地址:https://www.cnblogs.com/yyjxx2010xyu/p/5533846.html