zoukankan      html  css  js  c++  java
  • 树形DP入门 POJ2342

    今天准备学树形DP,于是查看了POJ题目分类,打开了POJ2057,发现对于我来说太难了,做不了,于是找了一些入门题来学。

    poj2342 父子节点不同时选
    题意:
    一个树,每个点有一个“快乐”值,父子结点不能同时快乐,问这个结构的最大快乐值

    用act[i][0]表示编号为i的人不参加聚会,act[i][1]表示编号为i的人参加聚会。
    经过简单思考,可以得出状态转移方程: act[i][1] += act[son][0];
    act[i][0] += max(act[son][0], act[son][1]);
    因为要先计算叶子节点, 所以从根节点开始DFS。
    代码如下:

    typedef long long LL;
    typedef unsigned long long ULL;
    using namespace std;
    
    // bool Sqrt(LL n) { return (LL)sqrt(n) * sqrt(n) == n; }
    const double PI = acos(-1.0), ESP = 1e-10;
    const LL INF = 99999999999999;
    const int inf = 999999999, N = 6000 + 24;
    LL act[N][2];
    int cnt, head[N], n;
    struct Edge {
    	int to, _next;
    }e[N];
    
    void addEdge(int from, int to) {
    	e[cnt].to = to;
    	e[cnt]._next = head[from];
    	head[from] = cnt++;
    }
    
    void dfs(int cur) {
    	for(int i = head[cur]; i != -1; i = e[i]._next) {
    		int to = e[i].to;
    		dfs(to);
    		act[cur][0] += max(act[to][1], act[to][0]);
    		act[cur][1] += act[to][0];
    	}
    }
    
    int main()
    {
    	//freopen("in.txt", "r", stdin);
    	//freopen("out.txt", "w", stdout);
    	scanf("%d", &n);
    	memset(act, 0, sizeof act);
    	for(int i = 1; i <= n; i++) scanf("%lld", &act[i][1]);    //根据题意,读入i号参加聚会的快乐值
    	int a, b; cnt = 0;
    	memset(head, -1, sizeof head);
    	LL start = n * (n + 1) / 2;
    	while(scanf("%d%d", &a, &b) == 2 && (a || b)) {
    		addEdge(b, a);
    		start -= (LL)a;
    	}
    	dfs((int)start);            //start是根节点的编号
    	printf("%lld
    ", max(act[start][1], act[start][0]));
    
    	return 0;
    }
    
  • 相关阅读:
    python数据分析之ipython
    Django之文件下载
    mongodb学习之:主从复制
    Django之高级视图与URL
    Django之request对象
    tornado安全应用之用户认证
    tornado安全应用之cookie
    tornado之异步web服务二
    【原创】Linux基础之测试域名IP端口连通性
    【原创】大数据基础之Mesos+Marathon+Docker部署nginx
  • 原文地址:https://www.cnblogs.com/000what/p/11643236.html
Copyright © 2011-2022 走看看