zoukankan      html  css  js  c++  java
  • 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
    ",ans);
    241     }
    242     return 0;
    243 }
  • 相关阅读:
    JDBC_批量处理语句提高处理速度
    JDBC_获取插入记录的主键值
    JDBC_获取数据库连接
    SmartSprites 智能批量合并 CSS 雪碧图
    移动前端开发技巧摘录
    将已有项目提交到github/从github上pull到本地
    网页设计创新式布局与交互
    如何打好前端游击战
    jQuery Mobile十大常用技巧
    Javascript图片的懒加载与预加载
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10116334.html
Copyright © 2011-2022 走看看