bzoj 1131 简单树形dp

思路:随便想想就能想出来啦把。。。  卡了我一个vector。。。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int,int>
#define piii pair<int, pair<int,int> >

using namespace std;

const int N = 1e6 + 10;
const int M = 10 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-6;

int n, tot, head[N];
LL cnt[N], sum[N], dp[N];

struct Edge {
    int to, nx;
} edge[N << 1];

void add(int u, int v) {
    edge[tot].to = v;
    edge[tot].nx = head[u];
    head[u] = tot++;
}

void dfs1(int u, int p) {
    cnt[u] = 1;
    for(int i = head[u]; ~i; i = edge[i].nx) {
        int v = edge[i].to;
        if(v == p) continue;
        dfs1(v, u);
        cnt[u] += cnt[v];
        sum[u] += sum[v] + cnt[v];
    }
}

void dfs2(int u, int p) {
    if(p) {
        dp[u] = sum[u] + (dp[p] - (sum[u] + cnt[u]) + n - cnt[u]);
    }

    for(int i = head[u]; ~i; i = edge[i].nx) {
        int v = edge[i].to;
        if(v == p) continue;
        dfs2(v, u);
    }
}

int main() {
    memset(head, -1, sizeof(head));
    scanf("%d", &n);
    for(int i = 1; i < n; i++) {
        int u, v; scanf("%d%d", &u, &v);
        add(u, v);
        add(v, u);
    }

    dfs1(1, 0);

    dp[1] = sum[1];
    dfs2(1, 0);

    int ans = 1;
    for(int i = 1; i <= n; i++) {
        if(dp[ans] < dp[i]) {
            ans = i;
        }
    }

    printf("%d\n", ans);
    return 0;
}
/*
*/

原文地址:https://www.cnblogs.com/CJLHY/p/9183525.html

时间: 2024-10-13 00:59:03

bzoj 1131 简单树形dp的相关文章

hdu 1520Anniversary party(简单树形dp)

Anniversary party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4310    Accepted Submission(s): 1976 Problem Description There is going to be a party to celebrate the 80-th Anniversary of the

sgu 143 Long live the Queen 简单树形dp

// sgu 143  Long live the Queen 简单树形dp // // 题意:在树上选一个连通字图,使得节点的权值之和最大 // f[i] 表示以该节点为根的字图权值之和的最大值 // 则有 f[i] = w[i] + sigma(max(0,f[j])) i是j的父节点 // 最后在所有的f中挑个最大值就是答案.... #include <algorithm> #include <bitset> #include <cassert> #include

csu 2014 summer training day 3 简单树形dp

FZU 2157 题意:树上的节点可以打上0或1的标记,树的权值由两部分呢组成,点权和边权,有00.01.10.11四种组合的边权, 问最小权值和.以1节点为树根 分析:dp[x][0]表示x标记0后的最小的权值,dp[x][1]同理 那么每次可以计算dp[x][0],dp[x][1]: 例如dp[x][1]=min(dp[son][0]+lab[0][1]+val[1],dp[son][1]+bal[1][1]+val[1]); 具体看代码. 用bfs写的分层,深搜代码更简洁 1 #inclu

[Luogu P1122]最大子树和 (简单树形DP)

题面 传送门:https://www.luogu.org/problemnew/show/P1122 Solution 这是一道简单的树形DP题. 首先,我们可以转换一下题面,可以发现,题目要求我们求出一颗树上的最大联通子图. 因为我们是在树上取的,实际上就是取一颗子树. 这个就是最基础的树形DP模型了. 我们可以设f[i]表示我们选的子图以i为根所能取的子树的最大值. 转移是: f[i] = beauty[i] + xigema(max(f[j],0)) (也就是一颗树的孩子所能取的子树,如果

HDU 3899 简单树形DP

题意:一棵树,给出每个点的权值和每条边的长度, 点j到点i的代价为点j的权值乘以连接i和j的边的长度.求点x使得所有点到点x的代价最小,输出 虽然还是不太懂树形DP是什么意思,先把代码贴出来把. 这道题目的做法是:先进行一次DFS,以每个节点为根,求出它下面节点到它的数量和. 再进行一次DFS,以每个节点为根,求出它下面节点到它的花费总和. source code: #pragma comment(linker, "/STACK:16777216") //for c++ Compile

UVALive - 2038 Strategic game (无向+记忆化+简单树形DP)

题目链接:https://vjudge.net/problem/UVALive-2038 题意:给定一棵树,选择尽量少的点,使得每个没有选中的结点至少和一个已经选中的结点相邻.输出最少需要选择的节点数.思路:经典的二分图最小顶点覆盖, 也是经典的树形 DP AC代码: #include<stdio.h> #include<string.h> #include<vector> #include<algorithm> using namespace std; c

poj2342 Anniversary party 简单树形dp

http://poj.org/problem?id=2342 Anniversary party Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4322   Accepted: 2459 Description There is going to be a party to celebrate the 80-th Anniversary of the Ural State University. The Universi

poj1463(简单树形dp)

Strategic game Time Limit: 2000MS   Memory Limit: 10000K Total Submissions: 9313   Accepted: 4368 Description Bob enjoys playing computer games, especially strategic games, but sometimes he cannot find the solution fast enough and then he is very sad

BZOJ 4753 二分+树形DP

思路: 先二分答案 f[x][j]表示在x的子树里选j个点 f[x][j+k]=max(f[x][j+k],f[x][j]+f[v[i]][k]); 初始化 x!=0 -> f[x][1]=p[x]-s[x]*mid x=0 -> f[x][0]=0 类似4033的那样转移 看似O(n^3)实际O(n^2) 加一个二分 复杂度O(能过) //By SiriusRen #include <cstdio> #include <cstring> #include <al