Bzoj 3694: 最短路 树链剖分

3694: 最短路

Time Limit: 5 Sec  Memory Limit: 256 MB
Submit: 67  Solved: 34
[Submit][Status][Discuss]

Description

给出一个n个点m条边的无向图,n个点的编号从1~n,定义源点为1。定义最短路树如下:从源点1经过边集T到任意一点i有且仅有一条路径,且这条路径是整个图1到i的最短路径,边集T构成最短路树。 给出最短路树,求对于除了源点1外的每个点i,求最短路,要求不经过给出的最短路树上的1到i的路径的最后一条边。
 

Input

第一行包含两个数n和m,表示图中有n个点和m条边。
接下来m行,每行有四个数ai,bi,li,ti,表示图中第i条边连接ai和bi权值为li,ti为1表示这条边是最短路树上的边,ti为0表示不是最短路树上的边。

Output

输出n-1个数,第i个数表示从1到i+1的要求的最短路。无法到达输出-1。

Sample Input

5 9
3 1 3 1
1 4 2 1
2 1 6 0
2 3 4 0
5 2 3 0
3 2 2 1
5 3 1 1
3 5 2 0
4 5 4 0

Sample Output

6 7 8 5

HINT

 

 对于100%的数据,n≤4000,m≤100000,1≤li≤100000

 

Source

题解:
首先,先处理出最短路树中每个点i距源点1的最短距离dis[i]。
 因为要求不经过最短路树的最后一条边,所以要到一个点,必须要从和这个点在同一个环中的另外一边绕过去。
例如:设我们要到u点,我们还有不在最短路树上的两个点x,y。t为LCA(x,y)。假如u点在y到t的路径上,我们既然不能从1经过t到u,那我们只有从1 -> t -> x -> y ->u。这样我们可以用dis[x]+val[x][y]+dis[y]-dis[u]来更新ans。因为dis[u]是不变的,所以我们可以最后去减去dis[u]。之前只用维护dis[x]+val[x][y]+dis[y]即可。
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define MAXN 4010
  4 #define MAXM 100010
  5 #define INF 1e9
  6 struct node
  7 {
  8     int begin,end,value,next;
  9 }edge[MAXN*2];
 10 struct NODE
 11 {
 12     int left,right,mn,tag;
 13 }tree[MAXN*5];
 14 int cnt,Head[MAXN],n,size[MAXN],deep[MAXN],P[MAXN][12],dis[MAXN],pos[MAXN],belong[MAXN],s1[MAXM],s2[MAXM],s3[MAXM],SIZE;
 15 bool vis[MAXN];
 16 void addedge(int bb,int ee,int vv)
 17 {
 18     edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].value=vv;edge[cnt].next=Head[bb];Head[bb]=cnt;
 19 }
 20 void addedge1(int bb,int ee,int vv)
 21 {
 22     addedge(bb,ee,vv);addedge(ee,bb,vv);
 23 }
 24 int read()
 25 {
 26     int s=0,fh=1;char ch=getchar();
 27     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
 28     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
 29     return s*fh;
 30 }
 31 void dfs1(int u)
 32 {
 33     int i,v;
 34     size[u]=1;vis[u]=true;
 35     for(i=Head[u];i!=-1;i=edge[i].next)
 36     {
 37         v=edge[i].end;
 38         if(vis[v]==false)
 39         {
 40             deep[v]=deep[u]+1;
 41             dis[v]=dis[u]+edge[i].value;
 42             P[v][0]=u;
 43             dfs1(v);
 44             size[u]+=size[v];
 45         }
 46     }
 47 }
 48 void Ycl()
 49 {
 50     int i,j;
 51     for(j=1;(1<<j)<=n;j++)
 52     {
 53         for(i=1;i<=n;i++)
 54         {
 55             if(P[i][j-1]!=-1)P[i][j]=P[P[i][j-1]][j-1];
 56         }
 57     }
 58 }
 59 void dfs2(int u,int chain)
 60 {
 61     int k=0,i,v;
 62     pos[u]=++SIZE;belong[u]=chain;
 63     for(i=Head[u];i!=-1;i=edge[i].next)
 64     {
 65         v=edge[i].end;
 66         if(deep[v]>deep[u]&&size[v]>size[k])k=v;
 67     }
 68     if(k==0)return;
 69     dfs2(k,chain);
 70     for(i=Head[u];i!=-1;i=edge[i].next)
 71     {
 72         v=edge[i].end;
 73         if(deep[v]>deep[u]&&v!=k)dfs2(v,v);
 74     }
 75 }
 76 int LCA(int x,int y)
 77 {
 78     int i,j;
 79     if(deep[x]<deep[y])swap(x,y);
 80     for(i=0;(1<<i)<=deep[x];i++);i--;
 81     for(j=i;j>=0;j--)if(deep[x]-(1<<j)>=deep[y])x=P[x][j];
 82     if(x==y)return x;
 83     for(j=i;j>=0;j--)
 84     {
 85         if(P[x][j]!=-1&&P[x][j]!=P[y][j])
 86         {
 87             x=P[x][j];
 88             y=P[y][j];
 89         }
 90     }
 91     return P[x][0];
 92 }
 93 void Build(int k,int l,int r)
 94 {
 95     tree[k].left=l;tree[k].right=r;tree[k].tag=INF;
 96     if(l==r){tree[k].mn=INF;return;}
 97     int mid=(l+r)/2;
 98     Build(k*2,l,mid);
 99     Build(k*2+1,mid+1,r);
100 }
101 void Pushup(int k)
102 {
103     int l=k*2,r=k*2+1;
104     tree[k].mn=min(tree[l].mn,tree[r].mn);
105 }
106 void Pushdown(int k)
107 {
108     int l=k*2,r=k*2+1;
109     if(tree[k].tag!=INF)
110     {
111         tree[l].tag=min(tree[l].tag,tree[k].tag);
112         tree[r].tag=min(tree[r].tag,tree[k].tag);
113         tree[l].mn=min(tree[l].mn,tree[k].tag);
114         tree[r].mn=min(tree[r].mn,tree[k].tag);
115         tree[k].tag=INF;
116     }
117 }
118 void Change(int k,int l,int r,int C)
119 {
120     if(l<=tree[k].left&&tree[k].right<=r){tree[k].tag=min(tree[k].tag,C);tree[k].mn=min(tree[k].mn,C);return;}
121     Pushdown(k);
122     int mid=(tree[k].left+tree[k].right)/2;
123     if(r<=mid)Change(k*2,l,r,C);
124     else if(l>mid)Change(k*2+1,l,r,C);
125     else {Change(k*2,l,mid,C);Change(k*2+1,mid+1,r,C);}
126     Pushup(k);
127 }
128 void Solve_change(int x,int f,int C)
129 {
130     while(belong[x]!=belong[f])
131     {
132         Change(1,pos[belong[x]],pos[x],C);
133         x=P[belong[x]][0];
134     }
135     if(x!=f)Change(1,pos[f]+1,pos[x],C);
136 }
137 int Query(int k,int l,int r)
138 {
139     if(l<=tree[k].left&&tree[k].right<=r)return tree[k].mn;
140     Pushdown(k);
141     int mid=(tree[k].left+tree[k].right)/2;
142     if(r<=mid)return Query(k*2,l,r);
143     else if(l>mid)return Query(k*2+1,l,r);
144     else return min(Query(k*2,l,mid),Query(k*2+1,mid+1,r));
145 }
146 int Solve_query(int x,int f)
147 {
148     int MN=INF;
149     while(belong[x]!=belong[f])
150     {
151         MN=min(MN,Query(1,pos[belong[x]],pos[x]));
152         x=P[belong[x]][0];
153     }
154     if(x!=f)MN=min(MN,Query(1,pos[f]+1,pos[x]));
155     return MN;
156 }
157 int ask(int k,int lr)
158 {
159     if(tree[k].left==tree[k].right)return tree[k].mn;
160     Pushdown(k);
161     int mid=(tree[k].left+tree[k].right)/2;
162     if(lr<=mid)return ask(k*2,lr);
163     else return ask(k*2+1,lr);
164 }
165 int main()
166 {
167     int m,tot,i,a,b,l,t,lca,C;
168     n=read();m=read();
169     tot=0;
170     memset(Head,-1,sizeof(Head));cnt=1;
171     for(i=1;i<=m;i++)
172     {
173         a=read();b=read();l=read();t=read();
174         if(t==0)
175         {
176             s1[++tot]=a;s2[tot]=b;s3[tot]=l;
177         }
178         else addedge1(a,b,l);
179     }
180     memset(P,-1,sizeof(P));SIZE=0;
181     dfs1(1);Ycl();
182     dfs2(1,1);
183     Build(1,1,n);
184     //for(i=1;i<=n;i++)Change(1,pos[i],pos[i],dis[i]);
185     for(i=1;i<=tot;i++)
186     {
187         lca=LCA(s1[i],s2[i]);
188         C=dis[s1[i]]+dis[s2[i]]+s3[i];
189         Solve_change(s1[i],lca,C);
190         Solve_change(s2[i],lca,C);
191     }
192     for(i=2;i<=n;i++)
193     {
194         //t=Solve_query(i,1);
195         t=Query(1,pos[i],pos[i]);
196         //t=ask(1,pos[i]);
197         if(t==INF)printf("-1 ");
198         else printf("%d ",t-dis[i]);
199     }
200     return 0;
201 }

 

posted @ 2016-03-25 00:09  微弱的世界  阅读(686)  评论(0编辑  收藏  举报