随笔 - 531  文章 - 0  评论 - 3  阅读 - 10215 

一棵有点权的树,选择一些点,

使得每个点至少满足下列中的一个: 1.已被选择 2.父亲被选择 3.子节点至少有一个被选择

求点权和最小值

 

f[x][0]=SUM{ min(f[y][1],f[y][2] }

 f[x][2] = SUM { min(f[y][0],f[y][1],f[y][2]) } +a[I]

f[x][1] = min{ s-min(f[y][1],f[y][2]) + f[y][2] },s=sum{min(f[y][1],f[y][2] }  // 先假设子节点一个不选,求出s ,现在选择y ,即取 f[y][2], 

从s里去掉y的min() 值,改为f[y][2]

 

复制代码

#include <bits/stdc++.h>
using namespace std ;
 const int N=1999;
 
 int a[N],in[N],f[N][3];
 int all,go[N],nxt[N],hd[N],n;
 
  void add(int x,int y){ 
     go[++all]=y,nxt[all]=hd[x],hd[x]=all;
 }
 void dfs(int x){
     int i,s=0;
     f[x][2]=a[x];
     for(i=hd[x];i;i=nxt[i]){
        int y=go[i]; dfs(y);
       
       f[x][0]+=min(f[y][1],f[y][2]);
       f[x][2]+=min(f[y][0],min(f[y][1],f[y][2]));
       s+=min(f[y][1],f[y][2]); 
    }
    f[x][1]=1e9;
    for(i=hd[x];i;i=nxt[i]){
        int y=go[i]; 
        f[x][1]=min(f[x][1],s-min(f[y][1],f[y][2])+f[y][2]);
    }
 }
 int main(){
     int rt,i,x,y,T;
     cin>>n;
     
     for(i=1;i<=n;i++){
           cin>>x; cin>>a[x]>>T;
      while(T--) 
        cin>>y,in[y]++,add(x,y);    
    }
    for(rt=1;in[rt];) rt++;
    
    dfs(rt);
    cout<<min(f[rt][1],f[rt][2]);
 }
复制代码

 

posted on   towboat  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示