BZOJ1576: [Usaco2009 Jan]安全路经Travel(树链剖分)
Description
Input
* 第一行: 两个空格分开的数, N和M
* 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i
Output
* 第1..N-1行: 第i行包含一个数:从牛棚_1到牛棚_i+1并且避免从牛棚1到牛棚i+1最短路经上最后一条牛路的最少的时间.如果这样的路经不存在,输出-1.
Sample Input
4 5
1 2 2
1 3 2
3 4 4
3 2 1
2 4 3
输入解释:
跟题中例子相同
1 2 2
1 3 2
3 4 4
3 2 1
2 4 3
输入解释:
跟题中例子相同
Sample Output
3
3
6
输出解释:
跟题中例子相同
3
6
输出解释:
跟题中例子相同
解题思路:
先建出来最短路树(题目都提示到这个份上了)
然后考虑不走最后一条边那么就要从子节点走或者从一些其他非树边走。
可以证明最后只经过一条非树边
考虑非树边可以怎么走。
一条非树边可以造成的贡献就是其Lca到这两个点上的所有树边。
其答案就是ansx=disu+disv+lenu-v-disx
disx一定那么可以将disu+disv+lenu-v插入树链
最后求最小值就好了。
可以用树链剖分实现。
代码:
1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 const int N=100010; 6 int tr[N<<2]; 7 struct pnt{ 8 int hd; 9 int no; 10 int fa; 11 int tp; 12 int dp; 13 int dis; 14 int ind; 15 int wgt; 16 int mxs; 17 bool vis; 18 bool friend operator < (pnt x,pnt y) 19 { 20 return x.dis>y.dis; 21 } 22 }p[N]; 23 struct ent{ 24 int twd; 25 int lst; 26 int vls; 27 bool use; 28 }e[N<<2]; 29 std::priority_queue<pnt>Q; 30 /*class priority_queue{ 31 public: 32 void push(pnt x) 33 { 34 line[++siz]=x; 35 int nw=siz; 36 while((nw>>1)) 37 { 38 int nx=nw>>1; 39 if(line[nx].dis<line[nw].dis) 40 break; 41 std::swap(line[nw],line[nx]); 42 nw=nx; 43 } 44 return ; 45 } 46 void pop(void) 47 { 48 line[1]=line[siz--]; 49 int nw=1; 50 while((nw<<1)<=siz) 51 { 52 int nx=nw<<1; 53 if(nx<siz&&line[nx].dis>line[nx+1].dis) 54 nx++; 55 if(line[nw].dis<line[nx].dis) 56 break; 57 std::swap(line[nw],line[nx]); 58 nw=nx; 59 } 60 return ; 61 } 62 int top(void) 63 { 64 return line[1].no; 65 } 66 bool empty(void) 67 { 68 return siz==0; 69 } 70 private: 71 pnt line[N]; 72 int siz; 73 }Q;*/ 74 int n,m; 75 int cnt; 76 int dfn; 77 void ade(int f,int t,int v) 78 { 79 cnt++; 80 e[cnt].twd=t; 81 e[cnt].lst=p[f].hd; 82 e[cnt].vls=v; 83 p[f].hd=cnt; 84 return ; 85 } 86 void Dij(int x) 87 { 88 for(int i=1;i<=n;i++) 89 { 90 p[i].no=i; 91 p[i].dis=0x3f3f3f3f; 92 } 93 p[1].dis=0; 94 p[1].fa=1; 95 Q.push(p[x]); 96 while(!Q.empty()) 97 { 98 x=Q.top().no; 99 Q.pop(); 100 if(p[x].vis) 101 continue; 102 p[x].vis=true; 103 for(int i=p[x].hd;i;i=e[i].lst) 104 { 105 int to=e[i].twd; 106 if(p[to].dis>p[x].dis+e[i].vls) 107 { 108 p[to].fa=x; 109 p[to].dis=p[x].dis+e[i].vls; 110 Q.push(p[to]); 111 } 112 } 113 } 114 return ; 115 } 116 void Basic_dfs(int x,int f) 117 { 118 p[x].dp=p[f].dp+1; 119 p[x].wgt=1; 120 int maxs=-1; 121 for(int i=p[x].hd;i;i=e[i].lst) 122 { 123 int to=e[i].twd; 124 if(p[to].fa!=x||to==f) 125 { 126 e[i].use=true; 127 continue; 128 } 129 Basic_dfs(to,x); 130 p[x].wgt+=p[to].wgt; 131 if(maxs<p[to].wgt) 132 { 133 p[x].mxs=to; 134 maxs=p[to].wgt; 135 } 136 } 137 return ; 138 } 139 void Build_dfs(int x,int top) 140 { 141 if(!x) 142 return ; 143 p[x].tp=top; 144 p[x].ind=++dfn; 145 Build_dfs(p[x].mxs,top); 146 for(int i=p[x].hd;i;i=e[i].lst) 147 { 148 int to=e[i].twd; 149 if(p[to].fa!=x||p[to].ind) 150 continue; 151 Build_dfs(to,to); 152 } 153 return ; 154 } 155 int Lca(int x,int y) 156 { 157 while(p[x].tp!=p[y].tp) 158 { 159 if(p[p[x].tp].dp<p[p[y].tp].dp) 160 std::swap(x,y); 161 x=p[p[x].tp].fa; 162 } 163 if(p[x].dp>p[y].dp) 164 std::swap(x,y); 165 return x; 166 } 167 void update(int l,int r,int ll,int rr,int spc,int v) 168 { 169 if(l>rr||ll>r) 170 return ; 171 if(ll<=l&&r<=rr) 172 { 173 tr[spc]=std::min(tr[spc],v); 174 return ; 175 } 176 int mid=(l+r)>>1; 177 update(l,mid,ll,rr,spc<<1,v); 178 update(mid+1,r,ll,rr,spc<<1|1,v); 179 return ; 180 } 181 int query(int l,int r,int pos,int spc) 182 { 183 if(l==r) 184 return tr[spc]; 185 int ans=tr[spc]; 186 int mid=(l+r)>>1; 187 if(pos<=mid) 188 return std::min(query(l,mid,pos,spc<<1),ans); 189 else 190 return std::min(query(mid+1,r,pos,spc<<1|1),ans); 191 } 192 int main() 193 { 194 memset(tr,0x6f,sizeof(tr)); 195 scanf("%d%d",&n,&m); 196 for(int i=1;i<=m;i++) 197 { 198 int a,b,c; 199 scanf("%d%d%d",&a,&b,&c); 200 ade(a,b,c); 201 ade(b,a,c); 202 } 203 Dij(1); 204 Basic_dfs(1,1); 205 Build_dfs(1,1); 206 for(int i=1;i<=cnt;i+=2) 207 { 208 int x,y; 209 x=e[i].twd; 210 y=e[i+1].twd; 211 int val=e[i].vls+p[x].dis+p[y].dis; 212 int z=Lca(x,y); 213 if(e[i].use) 214 { 215 while(p[x].tp!=p[z].tp) 216 { 217 update(1,dfn,p[p[x].tp].ind,p[x].ind,1,val); 218 x=p[p[x].tp].fa; 219 } 220 if(x!=z) 221 update(1,dfn,p[z].ind+1,p[x].ind,1,val); 222 } 223 if(e[i+1].use) 224 { 225 while(p[y].tp!=p[z].tp) 226 { 227 update(1,dfn,p[p[y].tp].ind,p[y].ind,1,val); 228 y=p[p[y].tp].fa; 229 } 230 if(y!=z) 231 update(1,dfn,p[z].ind+1,p[y].ind,1,val); 232 } 233 } 234 for(int i=2;i<=n;i++) 235 { 236 int ans=0x3f3f3f3f; 237 ans=std::min(ans,query(1,dfn,p[i].ind,1)-p[i].dis); 238 if(ans==0x3f3f3f3f) 239 ans=-1; 240 printf("%d\n",ans); 241 } 242 return 0; 243 }