zoukankan      html  css  js  c++  java
  • CF671D:Roads in Yusland

    n<=300000个点的树,给m<=300000条带权路径(ui,vi,保证vi是ui的祖先)求覆盖整棵树每条边的最小权和。

    好题好姿势!直观的看到可以树形DP,f[i]表示把点i包括它爸爸下面那条边都覆盖的最小权,就用经过他爸爸那条边的所有路径,各条路径加上一些子树信息来更新即可。

    这样时间炸,那看看怎么优化。实际上我们不是在单纯地用一条路径更新答案,而是这样一个东西:

    其中红色那条是题目给的路径,实际上是加上蓝色边连接的点的f[i]来更新边2上端的那个点的答案的。也就是说,一条路径来更新答案,要在这条路径的尾部加上那些点权(1),然后在更新某个点的答案的时候加上这个点下面的这条路径的分叉(2)。而更新一个点的路径,其实都是这个点对应子树的路径。至于子树中那些够不到这个点的路径,只需在扫到头的时候把这条路径的答案变inf即可。

    为了实现这个操作,即找到“起点在子树里的所有路径的答案”,我们用dfs序给每个路径的起点(下端点)编号,再dfs求每个点的答案;每次求答案时,先把以该点为起点的新路径赋初值,即该点所有子树的f[j]和,并把终点在该点的路径答案置inf;然后给经过该点的路径加“分叉”;由于dfs序编号好了,能更新这个节点的路径(上面提到的起点在这个子树内的路径)是连续的一个区间,因此用个线段树维护区间min即可。

    至于加“分叉”,观察可以发现:假如经过i的某路径来自子树j,那么应该把它答案加上点i其他儿子的f和。所以在加“分叉”时只需要再枚举一次孩子,把孩子子树内所有的路径加上其他孩子的f[j]和即可。

    废话少说见代码!

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<stdlib.h>
      4 #include<algorithm>
      5 //#include<iostream>
      6 using namespace std;
      7 
      8 int n,m;
      9 #define maxn 300011
     10 struct Edge{int to,next;}edge[maxn*4];int first[maxn],start[maxn],end[maxn],le=2;
     11 void in(int x,int y,int* first) {edge[le].to=y;edge[le].next=first[x];first[x]=le++;}
     12 void insert(int x,int y,int* first) {in(x,y,first);in(y,x,first);}
     13 int dfn[maxn],Left[maxn],Right[maxn],Time=0;
     14 void dfs(int x,int fa)
     15 {
     16     Left[x]=Time+1;
     17     for (int i=start[x];i;i=edge[i].next)
     18     {
     19         Edge &e=edge[i];
     20         dfn[e.to]=++Time;
     21     }
     22     for (int i=first[x];i;i=edge[i].next)
     23     {
     24         Edge &e=edge[i];
     25         if (e.to!=fa) dfs(e.to,x);
     26     }
     27     Right[x]=Time;
     28 }
     29 #define LL long long
     30 LL val[maxn];
     31 const LL inf=1e15+233;
     32 struct SMT
     33 {
     34     struct Node
     35     {
     36         LL Min;
     37         LL add;
     38         int l,r;
     39         int ls,rs;
     40     }a[maxn*2];
     41     int size;
     42     SMT() {size=0;}
     43     void build(int &x,int L,int R)
     44     {
     45         x=++size;
     46         a[x].Min=inf;a[x].add=0;
     47         a[x].l=L;a[x].r=R;
     48         if (L==R) {a[x].ls=a[x].rs=0;}
     49         else
     50         {
     51             const int mid=(L+R)>>1;
     52             build(a[x].ls,L,mid);
     53             build(a[x].rs,mid+1,R);
     54         }
     55     }
     56     void build() {int x;build(x,1,m);}
     57     void up(int x)
     58     {
     59         const int &p=a[x].ls,&q=a[x].rs;
     60         a[x].Min=min(a[p].Min,a[q].Min);
     61     }
     62     void addsingle(int x,LL v)
     63     {
     64         a[x].Min+=v;
     65         a[x].Min=min(inf,a[x].Min);
     66         a[x].add+=v;
     67     }
     68     void down(int x)
     69     {
     70         const int &p=a[x].ls,&q=a[x].rs;
     71         if (a[x].add)
     72         {
     73             addsingle(p,a[x].add);
     74             addsingle(q,a[x].add);
     75             a[x].add=0;
     76         }
     77     }
     78     int ql,qr;LL v;
     79     void be(int x)
     80     {
     81         if (a[x].l==a[x].r) {a[x].Min=v;return;}
     82         down(x);
     83         const int mid=(a[x].l+a[x].r)>>1;
     84         if (ql<=mid) be(a[x].ls);
     85         if (ql> mid) be(a[x].rs);
     86         up(x);
     87     }
     88     void be(int p,LL v) {ql=qr=p;this->v=v;be(1);}
     89     void Add(int x)
     90     {
     91         if (ql<=a[x].l && a[x].r<=qr) {addsingle(x,v);return;}
     92         down(x);
     93         const int mid=(a[x].l+a[x].r)>>1;
     94         if (ql<=mid) Add(a[x].ls);
     95         if (qr> mid) Add(a[x].rs);
     96         up(x);
     97     }
     98     void Add(int L,int R,LL v) {if (L>R) return;ql=L;qr=R;this->v=v;Add(1);}
     99     LL query(int x)
    100     {
    101         if (ql<=a[x].l && a[x].r<=qr) return a[x].Min;
    102         down(x);
    103         const int mid=(a[x].l+a[x].r)>>1;LL ans=inf;
    104         if (ql<=mid) ans=min(ans,query(a[x].ls));
    105         if (qr> mid) ans=min(ans,query(a[x].rs));
    106         return ans;
    107     }
    108     LL query(int L,int R) {if (L>R) return inf;ql=L;qr=R;return query(1);}
    109 }t;
    110 LL f[maxn];
    111 void play(int x,int fa)
    112 {
    113     LL tot=0;
    114     for (int i=first[x];i;i=edge[i].next)
    115     {
    116         Edge &e=edge[i];if (e.to==fa) continue;
    117         play(e.to,x);
    118         tot=min(inf,f[e.to]+tot);
    119     }
    120     for (int i=start[x];i;i=edge[i].next)
    121     {
    122         Edge &e=edge[i];
    123         t.be(dfn[e.to],tot+val[e.to]);
    124     }
    125     for (int i=end[x];i;i=edge[i].next)
    126     {
    127         Edge &e=edge[i];
    128         t.be(dfn[e.to],inf);
    129     }
    130     if (x==1) f[1]=tot;
    131     else if (tot<inf)
    132     {
    133         for (int i=first[x];i;i=edge[i].next)
    134         {
    135             Edge &e=edge[i];if (e.to==fa) continue;
    136             t.Add(Left[e.to],Right[e.to],tot-f[e.to]);
    137         }
    138         f[x]=t.query(Left[x],Right[x]);
    139     }
    140     else f[x]=inf;
    141 }
    142 void play()
    143 {
    144     dfs(1,0);
    145     t.build();
    146     play(1,0);
    147 }
    148 int x,y;LL v;
    149 int main()
    150 {
    151     scanf("%d%d",&n,&m);
    152     for (int i=1;i<n;i++)
    153     {
    154         scanf("%d%d",&x,&y);
    155         insert(x,y,first);
    156     }
    157     for (int i=1;i<=m;i++)
    158     {
    159         scanf("%d%d%I64d",&x,&y,&val[i]);
    160         in(x,i,start);
    161         in(y,i,end);
    162     }
    163     play();
    164     printf(f[1]>=inf?"-1
    ":"%I64d
    ",f[1]);
    165     return 0;
    166 }
    View Code

    还有一种贪心写法哦!

  • 相关阅读:
    JavaScript 中的求值策略
    JavaScript中的reduce()的5个用例
    使用JavaScript检测空闲的浏览器选项卡,可以做些什么?
    前端优化代码
    你可能不需要在JavaScript使用switch语句
    Js中的compose函数和pipe函数
    css是什么格式的文件?
    h5和css3的新特性有哪些?
    ES2020的这些新功能令人期待
    WindowsServer2003服务器的性能监视
  • 原文地址:https://www.cnblogs.com/Blue233333/p/7480028.html
Copyright © 2011-2022 走看看