P1273 有线电视网

匿名 (未验证) 提交于 2019-12-02 23:56:01

题面

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

 

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