小胖守皇宫
树形dp
代码中f数组的空间是有点浪费的,f[maxn][5]即可
f[i][0]以i为根节点的子树i自己守卫自己
f[i][1]以i为根节点的子树i父亲守卫自己
f[i][2]以i为根节点的子树i儿子守卫自己
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1500+5;
const ll Inf=1e18;
ll f[maxn][3][3][3];
//i被自己监视,被儿子监视,被父亲监视
//f[i][0][0][0] 以i为根的子树且i上有侍卫且i父亲上有侍卫且i子节点上有侍卫
//f[i][1][1][1] 以i为根的子树且i上没有侍卫且i父亲上没有侍卫且i子结点上没有侍卫
int n,m;
bool fa[maxn];
struct edge{
int from,to,next;
}e[maxn*2];
int head[maxn],len,root;
void Insert(int x,int y){
e[++len].from=x;e[len].to=y;e[len].next=head[x];head[x]=len;
}
void dfs(int u){
ll tot=0x3f3f3f3f;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
dfs(v);
f[u][0][1][1]+=min(f[v][1][0][1],min(f[v][1][1][0],f[v][0][1][1]));
//u自己来守卫自己,子节点选取最优情况即可
f[u][1][0][1]+=min(f[v][0][1][1],f[v][1][1][0]);
//u父亲来守卫自己,子节点只能由子节点(u的孙子节点)或者自己守卫自己
f[u][1][1][0]+=min(f[v][0][1][1],f[v][1][1][0]);
tot=min(tot,f[v][0][1][1]-f[v][1][1][0]);
//u子节点来守卫自己,对于子节点来说可以是自己守卫自己也可以是子节点(u的孙子节点)守卫自己,至少有一个守卫u(可能会亏损)
//就够了,为了保证最优,选取亏损最小的
}
if(tot>0)f[u][1][1][0]+=tot;
//假设v都是子节点(u的孙子节点)来守卫自己,加上最小正差值以后会有一个的决策变成自己守卫自己
}
void work(){
scanf("%d",&n);
for(int i=1;i<=n;++i){
int id;scanf("%d",&id);
ll val;scanf("%lld",&val);
f[id][0][1][1]=val;
int cnt;scanf("%d",&cnt);
for(int j=1;j<=cnt;++j){
int x;scanf("%d",&x);
Insert(id,x);
fa[x]=1;
}
}
for(int i=1;i<=n;++i){
if(!fa[i]){
root=i;break;
}
}
dfs(root);
printf("%lld\n",min(f[root][0][1][1],f[root][1][1][0]));
}
int main(){
freopen("a.in","r",stdin);
work();
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库