该题,一节点可以被父节点,子节点,子节点的子节点影响,状态分为3种,0->被父节点影响,1->被子节点看守,2->被自己看守
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2000;
int f[N][3];
int head[N],ne[N],e[N],id=1;
int n;
bool connect[N];
void add(int a,int b)
{
e[id]=b;
ne[id]=head[a];
head[a]=id++;
}
void dfs(int u)
{
bool jud=false;
int res=0;
bool flag=false;
for(int i=head[u];i!=-1;i=ne[i])
{
int j=e[i];
dfs(j);
f[u][0]+=min(f[j][1],f[j][2]);//0->被父节点看守
f[u][1]+=min(f[j][1],f[j][2]);//1->被子节点看守
f[u][2]+=min(f[j][0],min(f[j][1],f[j][2]));//2->被自己看守
if(f[j][2] < f[j][1])
jud=true;
if(!res || f[res][2]-f[res][1] > f[j][2]-f[j][1])
res=j;
flag=true;
}
if(!jud)//如果没有子节点看守,则选一个子节点看守,该子节点从被子节点看守转换到被自己看守损耗最小
f[u][1]=f[u][1]+f[res][2]-f[res][1];
if(!flag)//如果是叶节点,则无法被子节点看守,子节点看守代价是无穷大
f[u][1]=0x3f3f3f3f;
}
int main()
{
cin>>n;
memset(head,-1,sizeof head);
memset(ne,-1,sizeof ne);
memset(f,0,sizeof f);
memset(connect,0,sizeof connect);
for(int i=1;i<=n;i++)
{
int father,num,son,fee;
cin>>father>>fee>>num;
f[father][2]=fee;
if(num)
{
for(int j=1;j<=num;j++)
{
cin>>son;
add(father,son);
connect[son]=1;
}
}
}
int res=0;
for(int i=1;i<=n;i++)
{
if(!connect[i])//找到所有的连通分量
{
dfs(i);
res+=min(f[i][1],f[i][2])==0?f[i][2]:min(f[i][1],f[i][2]);
}
}
cout<<res<<endl;
}