Bzoj 3694: 最短路 树链剖分
3694: 最短路
Time Limit: 5 Sec Memory Limit: 256 MBSubmit: 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
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 }