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
输入解释:
跟题中例子相同

Sample Output

3
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 }

 

posted @ 2018-12-13 20:51  Unstoppable728  阅读(197)  评论(0编辑  收藏  举报