[POJ3585]Accumulation Degree
题面
\(\text{Solution:}\)
有些题目不仅让我们做树型 \(\text{dp}\) ,而且还让我们换每个根分别做一次, 然后这样就愉快的 \(\text{TLE}\) 了,所以我们要用一种方法快速知道所有根的答案。
二次扫描与换根法:
就是先选任意点作根做一遍 \(\text{dp}\) ,求出相关信息,然后再从根往下 \(\text{dfs}\) ,对每一个节点往下走之前进行自顶向下的推导,计算出 "换根" 后的解。
就这题而言就是用父亲的换根后的答案来跟新自己换根前的答案,一般是 换根后父亲的答案+自己换根前的答案-自己对父亲换根后的贡献。
#include <set>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <assert.h>
#include <algorithm>
using namespace std;
#define fir first
#define sec second
#define pb push_back
#define mp make_pair
#define LL long long
#define INF (0x3f3f3f3f)
#define mem(a, b) memset(a, b, sizeof (a))
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define Debug(x) cout << #x << " = " << x << endl
#define travle(i, x) for (register int i = head[x]; i; i = nxt[i])
#define For(i, a, b) for (register int (i) = (a); (i) <= (b); ++ (i))
#define Forr(i, a, b) for (register int (i) = (a); (i) >= (b); -- (i))
#define file(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
#define ____ debug("go\n")
namespace io {
    static char buf[1<<21], *pos = buf, *end = buf;
    inline char getc()
    { return pos == end && (end = (pos = buf) + fread(buf, 1, 1<<21, stdin), pos == end) ? EOF : *pos ++; }
    inline int rint() {
        register int x = 0, f = 1;register char c;
        while (!isdigit(c = getc())) if (c == '-') f = -1;
        while (x = (x << 1) + (x << 3) + (c ^ 48), isdigit(c = getc()));
        return x * f;
    }
    inline LL rLL() {
        register LL x = 0, f = 1; register char c;
        while (!isdigit(c = getc())) if (c == '-') f = -1;
        while (x = (x << 1ll) + (x << 3ll) + (c ^ 48), isdigit(c = getc()));
        return x * f;
    }
    inline void rstr(char *str) {
        while (isspace(*str = getc()));
        while (!isspace(*++str = getc()))
            if (*str == EOF) break;
        *str = '\0';
    }
    template<typename T>
        inline bool chkmin(T &x, T y) { return x > y ? (x = y, 1) : 0; }
    template<typename T>
        inline bool chkmax(T &x, T y) { return x < y ? (x = y, 1) : 0; }
}
using namespace io;
const int N = 2e5 + 2;
int n, T;
int tot, head[N], ver[N<<1], nxt[N<<1], edge[N<<1];
int D[N], F[N], in[N];
void add(int u, int v, int w)
{ ver[++tot] = v, edge[tot] = w, nxt[tot] = head[u], head[u] = tot; }
void DFS(int u, int f)
{
    D[u] = 0;
    for (int i = head[u]; i; i = nxt[i])
        if (ver[i] != f)
        {
            DFS(ver[i], u);
            int v = ver[i];
            if (in[v] == 1) D[u] += edge[i];
            else D[u] += min(D[v], edge[i]);
        }
}
void DP(int u, int f)
{
    for (int i = head[u]; i; i = nxt[i])
        if (ver[i] != f)
        {
            int v = ver[i];
            if (in[u] == 1) F[v] = D[v] + edge[i];
            else F[v] = D[v] + min(F[u] - min(edge[i], D[v]), edge[i]);
            DP(v, u);
        }
}
int main() {
    T = rint();
    while (T --)
    {
        tot = 0; mem(head, 0); mem(in, 0); mem(D, 0); mem(F, 0);
        n = rint();
        for (int i = 1; i < n; ++ i)
        {
            int u = rint(), v = rint(), w = rint();
            add(u, v, w);
            add(v, u, w);
            in[u] ++, in[v] ++;
        }
        DFS(1, 0);
        F[1] = D[1];
        DP(1, 0);
        for (int i = 1; i <= n; ++ i)
            chkmax(F[1], F[i]);
        printf("%d\n", F[1]);
    }
}
[POJ3585]Accumulation Degree的更多相关文章
- poj3585 Accumulation Degree【树形DP】【最大流】
		Accumulation Degree Time Limit: 5000MS Memory Limit: 65536K Total Submissions:3151 Accepted: 783 ... 
- POJ3585:Accumulation Degree(换根树形dp)
		Accumulation Degree Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 3425 Accepted: 85 ... 
- POJ3585 Accumulation Degree  【树形dp】
		题目链接 POJ3585 题解 -二次扫描与换根法- 对于这样一个无根树的树形dp 我们先任选一根进行一次树形dp 然后再扫一遍通过计算得出每个点为根时的答案 #include<iostream ... 
- poj3585 Accumulation Degree[树形DP换根]
		思路其实非常简单,借用一下最大流求法即可...默认以1为根时,$f[x]$表示以$x$为根的子树最大流.转移的话分两种情况,一种由叶子转移,一种由正常孩子转移,判断一下即可.换根的时候由頂向下递推转移 ... 
- POJ3585 Accumulation Degree(二次扫描与换根法)
		题目:http://poj.org/problem?id=3585 很容易想出暴力.那么就先扫一遍. 然后得到了指定一个根后每个点的子树值. 怎么转化利用一下呢?要是能找出当前点的父亲的 “ 不含当前 ... 
- 题解 poj3585 Accumulation Degree (树形dp)(二次扫描和换根法)
		写一篇题解,以纪念调了一个小时的经历(就是因为边的数组没有乘2 phhhh QAQ) 题目 题目大意:找一个点使得从这个点出发作为源点,流出的流量最大,输出这个最大的流量. 以这道题来介绍二次扫描和换 ... 
- POJ3585 Accumulation Degree【换根dp】
		题目传送门 题意 给出一棵树,树上的边都有容量,在树上任意选一个点作为根,使得往外流(到叶节点,叶节点可以接受无限多的流量)的流量最大. 分析 首先,还是从1号点工具人开始$dfs$,可以求出$dp[ ... 
- $Poj3585\ Accumulation Degree$ 树形$DP/$二次扫描与换根法
		Poj Description 有一个树形的水系,由n-1条河道与n个交叉点组成.每条河道有一个容量,联结x与y的河道容量记为c(x,y),河道的单位时间水量不能超过它的容量.有一个结点是整个水系的发 ... 
- poj3585 Accumulation Degree(换根dp)
		传送门 换根dp板子题(板子型选手 题意: 一棵树确定源点和汇点找到最大的流量(拿出一整套最大瘤板子orz ; int head[maxn],tot; struct node { int nt,to; ... 
随机推荐
- 【luogu P1726 上白泽慧音】 题解
			题目链接:https://www.luogu.org/problemnew/show/P1726 菜 #include <stack> #include <cstdio> #i ... 
- 【luogu P2984 [USACO10FEB]给巧克力Chocolate Giving】 题解
			题目链接:https://www.luogu.org/problemnew/show/P2984 练习SPFA,把FJ当做起点,求出到所有牛的最短路,再把两个牛的相加. #include <cs ... 
- Tomcat 服务器体系结构
			connector 监听端口,监听到以后,交给 Engine 引擎 处理,引擎会根据请求找到对应的主机,找到主机后再去找对应的应用. 如果我们将 port 改为 80,那访问的时候就不用输入端口号,因 ... 
- 浅谈二分查找 JavaScript
			算法介绍 二分查找,也称折半查找,是一种在有序数组中查找特定元素的搜索算法.查找过程经历一下步骤: (1)从有序数组的中间的元素开始搜索,如果该元素正好是目标元素,则停止搜索并返回该元素的索引值,否则 ... 
- ndk-build 学习笔记
			# 必须以local_path 开头# 定位源文件LOCAL_PATH := $(call my-dir) #引入clear-vars.mk文件,清除除local_path以外的其他local_< ... 
- IOS NSNotification 通知
			一. 先看下官方对NSNotification通知的解释 1. NSNotification 通知 @interface NSNotification : NSObject <NSCopying ... 
- iOS Block界面反向传值小demo
			1.在第二个视图控制器的.h文件中定义声明Block属性: // 定义block @property (nonatomic, copy) void (^NextViewControllerBlock) ... 
- c# 调用服务返回结果模板化
			一般我们返回一个结果,主要有返回值,执行结果信息,所以定义一个类 public class QuestResult { /// <summary> /// 返回值 ... 
- mac 开启mysql日志
			step1: 进入终端进入mysql: step2 : 开启mysql日志 step3 : 查看mysql的日志文件所在位置 step4 : 在终端中用tail -f 命令打开该日志文件: 
- 原生js方面的兼容性问题
			1.关于获取行外样式 currentStyle 和 getComputedStyle 出现的兼容性问题 我们都知道js通过style不可以获取行外样式,当我们需要获取行外样式时: 我们一般通过这两 ... 
