首页 > 其他分享 >洛谷 P2458 [SDOI2006] 保安站岗 - 树形DP

洛谷 P2458 [SDOI2006] 保安站岗 - 树形DP

时间:2023-07-18 23:46:38浏览次数:47  
标签:洛谷 min int id P2458 DP 保安 节点 dp

P2458 保安站岗

思路:
树形DP
三个状态:

  • dp[i][0]:节点 i 位置放保安的最小花费
  • dp[i][1]:节点 i 位置不放保安,但被子节点的保安看守
  • dp[i][2]:节点 i 位置不放保安,但被父节点的保安看守

状态转移:

  • dp[i][0]:节点 i 位置放保安,那么它可以合并子节点任何状态的最小值;
  • dp[i][1]:节点 i 位置不放保安,但被子节点的保安看守,那么它可以合并一个子节点的状态 0 和其余子节点的状态 1 和状态 0 的小值;
  • dp[i][2]:节点 i 位置不放保安,但被父节点的保安看守,那么它可以合并子节点除了状态 2 以外的状态。

最终答案:
min(dp[root][0],dp[root][1])
root设置为没有父节点的节点

下为代码:

//>>>Qiansui
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x,y,sizeof(x))
#define debug(x) cout << #x << " = " << x << endl
#define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << endl
//#define int long long

using namespace std;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ull,ull> pull;
typedef pair<double,double> pdd;
/*

*/
const int maxm=15e2+5,inf=0x3f3f3f3f,mod=998244353;
int n, k[maxm], m;
vector<int> e[maxm];
vector<vector<int>> dp(maxm, vector<int>(3,0));

void dfs(int u,int fa){
	dp[u][0] = k[u];
	dp[u][2] = dp[u][1] = 0;
	int pos = inf,sum = 0;
	for(auto v : e[u]){
		if(v == fa) continue;
		dfs(v,u);
		dp[u][0] += min(dp[v][0], min(dp[v][1], dp[v][2]));
		dp[u][2] += min(dp[v][0], dp[v][1]);
		dp[u][1] += min(dp[v][0], dp[v][1]);
		if(dp[v][0] < dp[v][1]) ++sum;
		else pos = min(pos, dp[v][0] - dp[v][1]);
	}
	if(!sum) dp[u][1] += pos;
	return ;
}

void solve(){
	cin>>n;
	int root;
	for(int i=0; i < n; ++i){
		int id, r;
		cin >> id;
		cin >> k[id] >> m;
		while(m--){
			cin >> r;
			e[id].push_back(r);
			e[r].push_back(id);
		}
	}
	dfs(1, 0);
	cout << min(dp[1][0], dp[1][1]) << '\n';
	return ;
}

signed main(){
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int _=1;
	// cin>>_;
	while(_--){
		solve();
	}
	return 0;
}

仅存单向边做法不推荐

//>>>Qiansui
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x,y,sizeof(x))
#define debug(x) cout << #x << " = " << x << endl
#define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << endl
//#define int long long

using namespace std;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ull,ull> pull;
typedef pair<double,double> pdd;
/*

*/
const int maxm=15e2+5,inf=0x3f3f3f3f,mod=998244353;
int n, k[maxm], m;
vector<int> e[maxm];
vector<vector<int>> dp(maxm, vector<int>(3,0));

void dfs(int u){
	dp[u][0] = k[u];
	dp[u][2] = dp[u][1] = 0;
	int pos = inf;
	for(auto v : e[u]){
		dfs(v);
		dp[u][0] += min(dp[v][0], min(dp[v][1], dp[v][2]));
		dp[u][2] += min(dp[v][0], dp[v][1]);
		dp[u][1] += min(dp[v][0], dp[v][1]);
		pos = min(pos, dp[v][0] - min(dp[v][0], dp[v][1]));
	}
	dp[u][1] += pos;
	return ;
}

void solve(){
	cin>>n;
	int root;
	vector<bool> vis(n+1, false);
	for(int i=0; i < n; ++i){
		int id, r;
		cin >> id;
		cin >> k[id] >> m;
		while(m--){
			cin >> r;
			e[id].push_back(r);
			vis[r]=true;
		}
	}
	for(int i = 1; i <= n; ++i){
		if(!vis[i]){
			root=i; break;
		}
	}
	dfs(root);
	cout << min(dp[root][0], dp[root][1]) << '\n';
	return ;
}

signed main(){
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int _=1;
	// cin>>_;
	while(_--){
		solve();
	}
	return 0;
}

相关资料

思路来源:
https://www.luogu.com.cn/blog/Parabola/solution-p2458

标签:洛谷,min,int,id,P2458,DP,保安,节点,dp
From: https://www.cnblogs.com/Qiansui/p/17564368.html

相关文章

  • DP们
    CF1763DValidBitonicPermutations巨大多分类讨论。枚举\(n\)的位置\(k\),分以下几类(默认\(i<j\),即\(x\)位置在\(y\)前面)。\(k<i,x>y\)\(k=i,x=n\)\(k>j,x<y\)\(k=j,y=n\)\(i<k<j\)前4种情况均可组合数乱搞,最后一种不会了,我来\(dp[i][j]\)表......
  • hdu 2227 Find the nondecreasing subsequences (树状数组+dp+离散化)
    题意:给定一个长度为n(n<=100000)的整数序列,求其中的递增序列的个数。对于某些序列中的递增序列的个数是可以用dp来求解的,其状态转移方程为:dp[i]=sum(dp[j])+1,j<i&&a[j]<a[i]根据状态转移方程可以得知这样dp的时间复杂度为O(n^2),而对于题目给定的10^6的数量级来说,这样......
  • 洛谷 P8923 -『MdOI R5』Many Minimizations
    怎么ARC还能撞题的?只能说Kubic牛逼。首先显然没法保序回归。考虑用类似于凸壳优化DP的做法解决原问题(也就是P4331):设\(dp_{i,j}\)表示考虑前\(i\)位,\(x_i=j\)的最小代价,显然有\(dp_{i,j}=\min_{k\lej}\{dp_{i-1,k}+|j-a_i|\}\)\(dp\)值显然是一个折线,用堆维护斜......
  • CS5212/CS5202 DP转VGA芯片设计方案
    CS5212内置MCU控制器,超低待机功率<100uW,用于设计DP端口到VGA转换器,也可以用于主板DP转VGA方案,CS5212AN芯片功能特性:2-lane通道VESADP1.1兼容接收机VGA输出接口,DAC速度高达210MHz,8位分辨率高达1920x1200x60(RB,缩小消隐),24位色深,1920x1440x60(RB,缩小消隐),或2048x152x60(RB,缩小消隐......
  • 决策单调性优化DP 学习笔记 & P4767 [IOI2000] 邮局 题解
    0.题面题目描述高速公路旁边有一些村庄。高速公路表示为整数轴,每个村庄的位置用单个整数坐标标识。没有两个在同样地方的村庄。两个位置之间的距离是其整数坐标差的绝对值。邮局将建在一些,但不一定是所有的村庄中。为了建立邮局,应选择他们建造的位置,使每个村庄与其最近的邮局......
  • 「数形结合」- 斜率优化 DP
    下面用例题来具体阐释斜率优化的思想。例1:P2365任务安排题目大意:有\(n\)个任务要在一台机器上一次完成,现在要将其划分为若干段,每一段的任务同时完成,且在每一段开始前需要启动时间\(s\)。第\(i\)个任务消耗\(t_i\)的时间,在\(T\)时刻完成需要消耗\(c_i\timesT\)的费......
  • Linux网络编程(socket的udp通信)
    UDP是无连接的,即发送数据之前不需要建立连接,它尽最大努力交付,即不保证可靠交付,在一些要求实时性的通信中多有用到如游戏,视频等,UDP是面向报文的,有别于tcp的一对一通信,udp支持一对一、一对多、多对一和多对多的交互通信等。 一、udp通信用到的相关函数解析intsocket(intdoma......
  • abc310e <公式递推(dp?)>
    题目E-NANDrepeatedly思路总结公式递推,找到相邻两项间的关系;代码Code#include<iostream>#include<algorithm>#include<vector>#include<cstring>usingnamespacestd;usingLL=longlong;usingPII=pair<int,int>;constintN=1e......
  • abc310d <dfs暴搜-分组方案数 / bitmask表示集合+dp>
    题目D-PeacefulTeams参考:https://www.cnblogs.com/legendstane/p/freee-programming-contest-2023-atcoder-beginner-contest-abc-310-solution.htmlhttps://blog.csdn.net/Muelsyse_/article/details/131747083思路方法1dfs暴搜由于数据范围极小,所以直接暴力即可......
  • 【DP】01背包与完全背包总结及空间优化
    01背包问题​ 题目描述:有n件物品,每件物品的重量为w[i],价值为c[i]。现在有一个容量为V的背包,问怎么选取物品放入背包,能使得背包内的总价值最大。其中每件物品只能放入一次。​ 样例:n=5,V=8w[i]=3,5,1,2,2c[i]=4,5,2,1,3​ 分析:使用暴力的解法,每件物品分为放......