P1273 有线电视网

核能气质少年 提交于 2019-11-28 20:55:39

题面

https://www.luogu.org/problem/P1273

题解

#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
using namespace std;

int n,m,k,w[3050],v,siz[3050];
vector<int> to[3050];
long long f[3050][3050];

struct node{
  int bro,son;
} tree[3050];

const long long inf=5e16;

void maketree(int x,int fa) {
  int i,l=to[x].size(),t;
  for (i=0;i<l;i++) if (to[x][i]!=fa) {
    if (tree[x].son==0) {
      tree[x].son=to[x][i];
      maketree(to[x][i],x);
    }
    else {
      t=tree[x].son;
      while (tree[t].bro!=0) t=tree[t].bro;
      tree[t].bro=to[x][i];
      maketree(to[x][i],x);
    }
  }
}

void treesum(int x){
  if (x>=n-m+1) siz[x]=1; else siz[x]=0;
  if (tree[x].bro!=0) {
    treesum(tree[x].bro);
    siz[x]+=siz[tree[x].bro];
  }
  if (tree[x].son!=0) {
    treesum(tree[x].son);
    siz[x]+=siz[tree[x].son];
  }
}

void treedp(int x,int d){
  int i;
  long long dpl,dpr;
  if (siz[x]<d) return;
  if (f[x][d]<=inf) return;
  if (d==0) return;
  f[x][d]=inf;
  if (tree[x].bro!=0) {
    treedp(tree[x].bro,d);
    f[x][d]=min(f[x][d],f[tree[x].bro][d]);
  }
  if (x>=n-m+1) {
    for (i=0;i<=d-1;i++) {
      if (tree[x].son!=0) {
        treedp(tree[x].son,i);
        dpl=f[tree[x].son][i];
      }
      else if (i==0) dpl=0; else dpl=inf/2;
      if (tree[x].bro!=0) {
        treedp(tree[x].bro,d-1-i);
        dpr=f[tree[x].bro][d-1-i];
      }
      else if (d-1-i==0) dpr=0; else dpr=inf/2;
      if (dpl+dpr+w[x]<f[x][d]) f[x][d]=dpl+dpr+w[x];
    }
  }
  else {
    for (i=0;i<=d;i++) {
      if (tree[x].son!=0) {
        treedp(tree[x].son,i);
        dpl=f[tree[x].son][i];
      } 
      else if (i==0) dpl=0; else dpl=inf/2;
    
      if (tree[x].bro!=0) {
        treedp(tree[x].bro,d-i);
        dpr=f[tree[x].bro][d-i];
      }
      else if (d-i==0) dpr=0; else dpr=inf/2;
    
      if (dpl+dpr+w[x]<f[x][d]) f[x][d]=dpl+dpr+w[x];
    }
  }
  return;
}

int main(){
  int i,j,a,c;
  scanf("%d %d",&n,&m);
  w[1]=0;
  for (i=1;i<=n-m;i++) {
    scanf("%d",&k);
    for (j=1;j<=k;j++) {
      scanf("%d %d",&a,&c);
      w[a]=c;
      to[i].push_back(a);
    }
  }
  for (i=n-m+1;i<=n;i++) {
    scanf("%d",&v);
    w[i]-=v;
  }
  maketree(1,0);
  treesum(1);
  memset(f,1,sizeof(f));
  for (i=1;i<=n;i++) f[i][0]=0;
  for (i=m;i>=0;i--) {
    treedp(1,i);
    if (f[1][i]<=0) {
      cout<<i<<endl;
      return 0;
    }
  }
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!