T3:blockenemy

blockenemy.pas/in/out 128M 1s

你在玩电子游戏的时候遇到了麻烦。。。。。。

你玩的游戏是在一个虚拟的城市里进行,这个城市里有n个点,都从0~n-1编了号,每两个点之间有且仅有一条路径。现在,你的敌人到这个城市来踩点了!!!为了阻止他们更好的踩点,

你决定切断他们所有踩点人员的联系,使他们孤军作战,然后在各个击破。但是这就要切断某些街道,而你每切断一条路,市民就会产生相对的不满值,不满值越大,城市的和谐度就越小。所以你现在需要知道为了使踩点人员所在的点两两之间不联通所切断的边产生的最小不满值是多少?

Input

第一行一个数:n  n<=50

以下n-1行,每行3个数 a,b,c  表示a点和b点之间有条路,切断这条路的不满值为c

以下若干行  每行一个数,表示踩点人员的位置

Output

一个数,最小不满值

Sample Input

5

1 0 1

1 2 2

0 3 3

4 0 4

3

2

4

Sample Output

4

据说这道题有许多做法,直接复制题面的第一句话到百度里搜索,就会有别人的做法,我的做法是std的,想了好久才搞定。

对于每个节点i,令f(i, 0)表示以i为根的子树中,全部敌人两两不连通,且全部都无法到达点i的最小值;f(i, 1)表示以i为根的子树中,全部敌人两两不连通,但有1个敌人可以到底点i的最小值。状态设计好了,接下来就是分两种情况转移:

情况①:若i这个点有敌人。显然,f(i, 0)肯定为inf了,因为不可能做到“全部都无法到达点i”。f(i, 1) = sigma(min(f(j, 1) + w(i, j), f(j, 0))),其中j属于i的儿子。

情况②:若i这个点没敌人。那么

f(i, 0) = sigma(min(f(j, 1) + w(i, j), f(j, 0))),其中j属于i的儿子。

f(i, 1)的转移有那么一丢丢难想。f(i, 1)一定实在f(i, 0)的基础上,使得某个儿子从不能到达i,变成能到达i,即对于儿子j,对该状态的贡献由min(f(j, 1) + w, f(j, 0))变为f(j, 1).如果这样的话,f(i, 1)就会在f(i, 0)的基础上减去min(f(j, 1) + w, f(j, 0)) - f(j, 1),那么这个值越大,f(i, 1)就会越小。

#include <cstdio>
#include <cstdlib>
#include <cstring> const int maxn = 55; int n, t1, t2, t3, root, f[maxn][2];
bool book[maxn];
struct graph {
int head[maxn], to[maxn << 1], next[maxn << 1], w[maxn << 1], lb;
graph(void) {
memset(head, -1, sizeof head);
memset(next, -1, sizeof next);
lb = 0;
}
void ist(int aa, int ss, int ww) {
to[lb] = ss;
w[lb] = ww;
next[lb] = head[aa];
head[aa] = lb;
++lb;
}
} g; inline int minn(int aa, int ss) {
return aa < ss? aa: ss;
}
inline int maxx(int aa, int ss) {
return aa > ss? aa: ss;
}
void dfs(int r, int p) {
if (book[r]) {
f[r][0] = 0x3c3c3c3c;
for (int j = g.head[r]; j != -1; j = g.next[j]) {
if (g.to[j] != p) {
dfs(g.to[j], r);
f[r][1] += minn(f[g.to[j]][1] + g.w[j], f[g.to[j]][0]);
}
}
}
else {
int mx = 0, mn;
for (int j = g.head[r]; j != -1; j = g.next[j]) {
if (g.to[j] != p) {
dfs(g.to[j], r);
mn = minn(f[g.to[j]][0], f[g.to[j]][1] + g.w[j]);
f[r][0] += mn;
mx = maxx(mx, mn - f[g.to[j]][1]);
}
}
f[r][1] = f[r][0] - mx;
}
} int main(void) {
freopen("blockenemy.in", "r", stdin);
freopen("blockenemy.out", "w", stdout);
scanf("%d", &n);
unsigned seed;
for (int i = 1; i < n; ++i) {
scanf("%d%d%d", &t1, &t2, &t3);
seed += t1 + t2 + t3;
g.ist(t1, t2, t3);
g.ist(t2, t1, t3);
}
while (scanf("%d", &t1) != EOF) {
book[t1] = true;
seed += t1;
} srand(seed);
root = rand() % n;
dfs(root, -1);
printf("%d\n", f[root][1]);
return 0;
}

  

[ZPG TEST 108] blockenemy【树形dp】的更多相关文章

  1. [vijos 1642]班长的任务 [树形dp]

    背景 十八居士的毕业典礼(1) 描述 福州时代中学2009届十班同学毕业了,于是班长PRT开始筹办毕业晚会,但是由于条件有限,可能每个同学不能都去,但每个人都有一个权值,PRT希望来的同学们的权值总和 ...

  2. [CEOI2007]树的匹配Treasury(树形DP+高精)

    题意 给一棵树,你可以匹配有边相连的两个点,问你这棵树的最大匹配时多少,并且计算出有多少种最大匹配. N≤1000,其中40%的数据答案不超过 108 题解 显然的树形DP+高精. 这题是作为考试题考 ...

  3. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

  4. COGS 2532. [HZOI 2016]树之美 树形dp

    可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...

  5. 【BZOJ-4726】Sabota? 树形DP

    4726: [POI2017]Sabota? Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 128  Solved ...

  6. 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)

    题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...

  7. 树形DP

    切题ing!!!!! HDU  2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...

  8. BZOJ 2286 消耗战 (虚树+树形DP)

    给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...

  9. POJ2342 树形dp

    原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...

随机推荐

  1. javascript array-like object

    http://www.nfriedly.com/techblog/2009/06/advanced-javascript-objects-arrays-and-array-like-objects/ ...

  2. [Tools] Create a Chrome Extension

    Creating a Chrome extension requires a manifest.json file which defines how your extension will beha ...

  3. python的线程thread笔记

    python的线程是用thread和threading来实现的.其中利用threading会更好,因为thread没有线程保护,当主线程退出了之后,子线程也会被强行退出.threading支持守护线程 ...

  4. Mongodb for PHP教程之入门安装

    简介: MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.他支持的数据结构非常松散,是类似json的bjson格式,因此可以存储比较复杂的数据 ...

  5. C语言将10进制转为2进制

    第一种方法: #include<stdio.h> void dectobin(int n); int main() { int x=0; scanf("%d",& ...

  6. 将C++的标识符转成OC的标识符

    3.将C++的标识符转成OC的标识符 C++的标识符和OC一样由数字字母下划线组成.打头的不是数字.当标识符超过一个单词, C++採用全字母小写.单词间用下划线连接的书写规范,如: bei_jing ...

  7. windows下使用mingw和msys编译GOTOBLAS和OpenBLAS

    在windows下利用msys编译openBLAS若遇到错误提示: gcc: CreateProcess : No such file or directory 问题原因参考:http://www.c ...

  8. web 开发之js---页面缓存, jsp 缓存, html 缓存, ajax缓存,解决方法

    有关页面缓存问题.这个问题上网找了好多.但发觉各种解决方法,都彼此分离,没有一篇统一的解决方法,本人近日,也遇到了页面缓存的问题,根据网上各页面缓存的解答,做了一个总结. 1.服务器端缓存的问题, 防 ...

  9. SQL Server 存储过程具体解释

    SQL Server 存储过程具体解释 存储过程的优缺点 ◆长处: 运行速度更快. 存储过程仅仅在创造时进行编译,而一般SQL语句每运行一次就编译一次,所以使用存储过程运行速度更快. 存储过程用于处理 ...

  10. mysql命令行爱好者必备工具mycli

    mycli MyCLI is a command line interface for MySQL, MariaDB, and Percona with auto-completion and syn ...