zoukankan      html  css  js  c++  java
  • JZOJ2678 树B

    Description

    已知无向连通图G由N个点,N-1条边组成。每条边的边权给定。现要求通过删除一些边,将节点1与另M个指定节点分开,希望删除的边的权值和尽量小,求此最小代价。

    Input

    每个输入文件中仅包含一个测试数据。

    第一行包含两个整数N,M。

    第二行至第N行每行包含3个整数,A、B、C,表示节点A与节点B有一条边相连,边权为C。

    第N+1行至第N+M行每行包含一个整数X,表示要求与节点1分开的节点。

    Output

    输出文件仅包含一个整数,表示最小代价。

    思路

     树的遍历+DP

    不知道为什么大家都喜欢叫树形DP,好高逼的感觉.害得我昨天那题一听是什么"树形DP"就不敢写了

    对于每个必删的点 i ,很容易想到我们不必遍历以其为根的子树,
      这样的情况花费是 cost[i]=E[V[i].dad->V[i]]

    对于一个不必删的点 j ,
     删掉其子树中所有必删的点的花费是
       cost[j]=SUM(cost[儿子1]+cost[儿子2]+......+cost[儿子n]);
     我们可以考虑删掉以其为根的子树,这样当然就删除了其子树中的所有必删点
      花费 cost[j]=E[V[i].dad->V[i]]

    考虑最小情况,所以点 n 的值应为 min(E[V[i].dad->V[i]],SUM(cost[儿子1]+cost[儿子2]+......+cost[儿子n]))

    由于树的性质,每个点的DP值只给自己父亲用,所以不必存下,利用返回值带回即可.

    代码(有问题欢迎讨论)

     1 #include <iostream>
     2 #include <algorithm>
     3 using namespace std;
     4 
     5 int N,M;
     6 
     7 struct edge{int fr,to,vl;}E[2000000];
     8 int cmpS(edge m,edge n){return (m.fr==n.fr)?(m.to<n.to):(m.fr<n.fr);}
     9 
    10 struct node{int l,r,flag,vl;}V[1000001];
    11 
    12 int dfs(int dad,int dv,int id){//他老爸是谁(李刚) / 他到他老爸多远 / 他是谁
    13     if(V[id].flag==1)//要删就删,不多话
    14         return dv;
    15     int s=0;//儿子的和SUM(没儿子返回0)
    16     for(int i=V[id].l;i<=V[id].r;++i){
    17         if(E[i].to!=dad){//你爸爸还是你爸爸,只能找自己儿子
    18             s+=dfs(id,E[i].vl,E[i].to);
    19         }
    20     }
    21     return min(dv,s);
    22 }
    23 
    24 int main(){
    25     
    26 // 输入数据
    27     cin>>N>>M;
    28     for(int i=1;i<N;++i)//无向图存成两个有向边
    29         cin>>E[i].fr>>E[i].to>>E[i].vl,E[N-1+i]={E[i].to,E[i].fr,E[i].vl};
    30     for(int i=1,a;i<=M;++i)
    31         cin>>a,V[a].flag=1;//标记要删
    32 // 初始化图
    33     for(int i=1;i<=N;++i)
    34         V[i]={0,-1,V[i].flag,0};
    35     sort(&E[1],&E[2*N-1],cmpS);
    36     for(int i=1;i<=2*N-1;++i){
    37         if(E[i].fr!=E[i-1].fr){
    38             V[E[i].fr].l=i;
    39             V[E[i-1].fr].r=i-1;
    40         }
    41     }
    42 // 深搜/输出
    43     cout<<dfs(0,1e9,1);//可怜的根节点没爸爸所以他离他爸很远(要不你当他爸做根节点//别打我)
    44     
    45     return 0;
    46     
    47 }
    能理解尽量自己码

    淼仔mxxr第一次在博客写题解,大佬轻喷.

  • 相关阅读:
    BZOJ
    BZOJ
    BZOJ
    BZOJ
    BZOJ
    BZOJ
    [知识点]平衡树之Splay
    [BZOJ1015/JSOI2008]星球大战
    [知识点]状态压缩DP
    [NOIP2011]聪明的质检员
  • 原文地址:https://www.cnblogs.com/mxxr/p/11143103.html
Copyright © 2011-2022 走看看