• P2458 [SDOI2006]保安站岗


    在这里插入图片描述
    在这里插入图片描述

    题意:给你一个树带点权.你花费一个点的点权,然后覆盖掉父亲自己和儿子.
    我怎么又见过你了Uva1218完美服务,Cf1029E是嘛
    类似的套路,分类成3种情况.
    d p ( u , 0 ) dp(u,0) dp(u,0): u u u被自己覆盖,花费 a u 点亮 u 点 a_u点亮u点 au点亮u
    d p ( u , 0 ) = a u + ∑ m i n ( d p ( v , 1 ) , d p ( v , 2 ) , d p ( v , 0 ) ) dp(u,0)=a_u+\sum min(dp(v,1),dp(v,2),dp(v,0)) dp(u,0)=au+min(dp(v,1),dp(v,2),dp(v,0))
    d p ( u , 1 ) dp(u,1) dp(u,1): u u u被父亲覆盖,但自己不花费的情况
    d p ( u , 1 ) = ∑ m i n ( d p ( v , 0 ) , d p ( v , 2 ) ) dp(u,1)=\sum min(dp(v,0),dp(v,2)) dp(u,1)=min(dp(v,0),dp(v,2))
    d p ( u , 2 ) : dp(u,2): dp(u,2): u u u不被父亲覆盖,而且自己不花费,由儿子中的一个覆盖的情况
    转移数学不好写,程序好写,挑选一个儿子是 d p ( v , 0 ) dp(v,0) dp(v,0)的状态,其余儿子取 m i n ( d p ( v , 0 ) , d p ( v , 2 ) ) min(dp(v,0),dp(v,2)) min(dp(v,0),dp(v,2)).
    挑选过程for循环就行
    注意,叶子不能状态2,直接返回一个INF即可.

    #include
    using namespace std;
    const int maxn = 1e6+5;
    const long long INF = 1e10+7;
    typedef long long ll;
    typedef pair<int,int> pii;
    #define all(a) (a).begin(), (a).end()
    #define pb(a) push_back(a)
    vector<int> G[maxn];
    int a[maxn];ll dp[maxn][3];
    ll dfs(int u,int fa,int st){
    	ll &ans = dp[u][st];
    	if(ans!=-1) return ans;
    	ans = 0;
    	if(st==0) ans = a[u];
    	vector<pair<ll,ll> > tmp;
    	int child=0;
    	for(auto v : G[u]){
    		if(v==fa) continue;
    		child++;
    		if(st==0){
    			ans += min(dfs(v,u,0),min(dfs(v,u,1),dfs(v,u,2))); 
    		}
    		else if(st==1) ans+=min(dfs(v,u,0),dfs(v,u,2));
    		else tmp.push_back({dfs(v,u,0),dfs(v,u,2)});
    	}
    	//叶子不能是状态2
    	if(st==2&&!child) return ans=INF;
    	if(st==2){
    		ans = INF;ll res = 0;
    		for(auto [a,b]:tmp) res+=min(a,b);
    		for(auto [a,b]:tmp) ans =min(ans,res-min(a,b)+a);  
    	}
    	return ans;
    }
    int main(){
        ios::sync_with_stdio(false);
    	cin.tie(0);
    	cout.tie(0);
    	int n;cin>>n;
    	memset(dp,-1,sizeof(dp));
    	for(int i=1,u,v,num;i<=n;i++){
    		cin>>u>>a[u]>>num;
    		for(int j=1;j<=num;j++){
    			cin>>v;G[u].pb(v);G[v].pb(u);
    		}
    	}
    	cout<<min(dfs(1,0,0),dfs(1,0,2))<<"\n";
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
  • 相关阅读:
    【Linux】System V 信号量
    spark深度剖析
    Linux下快速搭建YApi接口管理平台
    这个故事改善了我的焦虑 小故事大智慧 如何摆脱烦恼
    C++基础知识(十)--- I/O
    中石化、中石油接口文档源码分享
    MindSponge分子动力学模拟——增强采样(2024.11)
    【论文阅读】Prototypical Networks for Few-shot Learning
    算法通关村-----回溯模板如何解决排列组合问题
    OpenCV入门8:区域分割和区域生长
  • 原文地址:https://blog.csdn.net/qq_36018057/article/details/126563150