zoukankan      html  css  js  c++  java
  • 皇宫看守

    https://loj.ac/problem/10157

    题目描述

      有一个树形宫殿,每个节点放置守卫有一定费用,一个点被放置时与这个点相连的点可以被看守到,求看守所有节点的最小花费。

    思路

      为了保证状态之间没有重叠,我们记(f[i][0])为放该节点,(f[i][1])为不放该节点,也不放该节点的子节点,(f[i][2])为不放该节点,放该节点的子节点的最小代价。对于放该节点,无所谓子节点的状态。对于(f[i][1]),我们必须放子节点的子节点。而放子节点的情况,我们暴力枚举必须放某个子节点的代价,取最小值即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=1600;
    
    int read()
    {
    	int res=0,w=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){res=(res<<3)+(res<<1)+(ch^48);ch=getchar();}
    	return res*w;
    }
    void write(int x)
    {
    	if(x<0){putchar('-');x=-x;}
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    }
    
    vector<int>son[N];
    int f[N][4],s[N];
    void dfs(int u)
    {
    	f[u][0]=s[u];
    	int ss=0;
    	for(int i=0;i<son[u].size();i++)
    	{
    		int v=son[u][i];
    		dfs(v);
    		f[u][0]+=min(f[v][0],min(f[v][1],f[v][2]));
    		f[u][1]+=f[v][2];
    		ss+=min(f[v][0],f[v][2]);
    	}
    	f[u][2]=1e8;
    	for(int i=0;i<son[u].size();i++)
    	{
    		int v=son[u][i];
    		f[u][2]=min(f[u][2],ss-min(f[v][0],f[v][2])+f[v][0]);
    	}
    }
    
    bool a[N];
    int main() 
    {
    	int n=read(),root;
    	for(int i=1;i<=n;i++)
    	{
    		int x=read();s[x]=read();
    		int m=read();
    		while(m--)
    		{
    			int y=read();
    			son[x].push_back(y);
    			a[y]=1;
    		}
    	}
    	for(int i=1;i<=n;i++)
    		if(!a[i])root=i;
    	dfs(root);
    	write(min(f[root][0],f[root][2]));
    }
    
  • 相关阅读:
    全栈工程师学习Linux技术的忠告
    实战CentOS系统部署Hadoop集群服务
    如何安装最新的 XFCE 桌面?
    scrapy爬虫框架(二)
    scrapy爬虫框架(一)
    数据结构与算法(二)
    IDEA 常用快捷键
    数据结构与算法(一)
    es6之模板字符串
    es6之箭头函数
  • 原文地址:https://www.cnblogs.com/fangbozhen/p/11838403.html
Copyright © 2011-2022 走看看