SCUT - 274 - CC B-Tree - 树形dp
首先要判断是一颗树,并且找出树的直径。
是一棵树,首先边恰好有n-1条,其次要连通,这两个条件已经充分了,当然判环可以加速。
两次dfs找出直径,一边叫做L,另一边叫做R。(第一次写这个)
然后树形dp。
规定其中一个叶子作为树根。然后fx表示从x向下(叶子)走能走到的最远距离,这个非常简单。
然后漏了什么情况呢?从x向上走的情况。
这个时候要从根开始维护一个叫做gx的数组,那么每次孩子v的gx就是父亲u的gx(继续向上走)和u的fx(从父亲开始往下走)的最大值。注意这个时候往下走的不能走回去v,所以要记录两个fx,并且记录大的那个是走哪个方向的。
边界:在叶子/树根等不能走的位置,根据定义,距离为0,点序号为本身。
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
const int INF = 0x3f3f3f3f;
struct Edge {
int v, w;
};
vector<Edge> e[MAXN];
void init0(int n) {
for(int i = 0; i <= n; ++i)
e[i].clear();
}
int cnt, vis[MAXN], dis[MAXN], maxdis, L, R;
void init1(int n) {
memset(vis, false, sizeof(vis[0]) * (n + 1));
memset(dis, 0, sizeof(dis[0]) * (n + 1));
cnt = 0, maxdis = 0;
}
bool dfs1(int id, int fa) {
vis[id] = true, ++cnt;
for(auto p : e[id]) {
int v = p.v, w = p.w;
if(v == fa)
continue;
if(vis[v])
return false;
dis[v] = dis[id] + w;
if(dis[v] > maxdis)
maxdis = dis[v], L = v;
if(dfs1(v, id) == false)
return false;
}
return true;
}
void init2(int n) {
memset(dis, 0, sizeof(dis[0]) * (n + 1));
maxdis = 0;
}
void dfs2(int id, int fa) {
for(auto p : e[id]) {
int v = p.v, w = p.w;
if(v == fa)
continue;
dis[v] = dis[id] + w;
if(dis[v] > maxdis)
maxdis = dis[v], R = v;
dfs2(v, id);
}
}
struct F {
int v, w, s;
F(int v = 0, int w = 0, int s = 0): v(v), w(w), s(s) {}
} f[MAXN], f2[MAXN], tmp;
void maintainF(int id) {
if(tmp.w > f2[id].w || tmp.w == f2[id].w && tmp.v < f2[id].v) {
f2[id] = tmp;
if(f2[id].w > f[id].w || f2[id].w == f[id].w && f2[id].v < f[id].v)
swap(f[id], f2[id]);
}
}
void dfs3(int id, int fa) {
f[id] = f2[id] = F(id, 0, -1);
for(auto p : e[id]) {
int v = p.v, w = p.w;
if(v == fa)
continue;
dfs3(v, id);
tmp.w = f[v].w + w, tmp.v = f[v].v, tmp.s = v;
maintainF(id);
}
}
struct G {
int v, w;
} g[MAXN];
F getF(int id, int fa) {
if(f[fa].s == id)
return f2[fa];
return f[fa];
}
void maintainG(int id, int fa, int faw) {
if(fa == 0) {
g[id].w = 0;
g[id].v = id;
return;
}
tmp = getF(id, fa);
if(g[fa].w > tmp.w) {
g[id].w = g[fa].w + faw;
g[id].v = g[fa].v;
} else if(g[fa].w == tmp.w) {
g[id].w = g[fa].w + faw;
g[id].v = min(tmp.v, g[fa].v);
} else {
g[id].w = tmp.w + faw;
g[id].v = tmp.v;
}
}
void dfs4(int id, int fa, int faw) {
maintainG(id, fa, faw);
for(auto p : e[id]) {
int v = p.v, w = p.w;
if(v == fa)
continue;
dfs4(v, id, w);
}
}
int getFG(int id) {
if(f[id].w > g[id].w)
return f[id].v;
else if(f[id].w == g[id].w)
return min(f[id].v, g[id].v);
return g[id].v;
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int n, m, k;
while(~scanf("%d%d%d", &n, &m, &k)) {
if(m != n - 1) {
for(int i = 1, u, v, w; i <= m; ++i)
scanf("%d%d%d", &u, &v, &w);
puts("There is no B-Tree");
continue;
}
init0(n);
for(int i = 1, u, v, w; i <= m; ++i) {
scanf("%d%d%d", &u, &v, &w);
e[u].push_back({v, w});
e[v].push_back({u, w});
}
init1(n);
if(dfs1(1, 0) == false || cnt != n) {
puts("There is no B-Tree");
continue;
}
init2(n);
dfs2(L, 0);
if(dis[R] > k) {
puts("There is no B-Tree");
continue;
}
dfs3(R, 0);
dfs4(R, 0, 0);
for(int i = 1; i <= n; ++i)
printf("%d\n", getFG(i));
}
}
SCUT - 274 - CC B-Tree - 树形dp的更多相关文章
- 熟练剖分(tree) 树形DP
熟练剖分(tree) 树形DP 题目描述 题目传送门 分析 我们设\(f[i][j]\)为以\(i\)为根节点的子树中最坏时间复杂度小于等于\(j\)的概率 设\(g[i][j]\)为当前扫到的以\( ...
- hdu-5834 Magic boy Bi Luo with his excited tree(树形dp)
题目链接: Magic boy Bi Luo with his excited tree Time Limit: 8000/4000 MS (Java/Others) Memory Limit: ...
- CF 461B Appleman and Tree 树形DP
Appleman has a tree with n vertices. Some of the vertices (at least one) are colored black and other ...
- codeforces 161D Distance in Tree 树形dp
题目链接: http://codeforces.com/contest/161/problem/D D. Distance in Tree time limit per test 3 secondsm ...
- hdu6035 Colorful Tree 树形dp 给定一棵树,每个节点有一个颜色值。定义每条路径的值为经过的节点的不同颜色数。求所有路径的值和。
/** 题目:hdu6035 Colorful Tree 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题意:给定一棵树,每个节点有一个颜色值.定 ...
- 5.10 省选模拟赛 tree 树形dp 逆元
LINK:tree 整场比赛看起来最不可做 确是最简单的题目. 感觉很难写 不过单独考虑某个点 容易想到树形dp的状态. 设f[x]表示以x为根的子树内有黑边的方案数. 白边方案只有一种所以不用记录. ...
- Codeforces Round #263 Div.1 B Appleman and Tree --树形DP【转】
题意:给了一棵树以及每个节点的颜色,1代表黑,0代表白,求将这棵树拆成k棵树,使得每棵树恰好有一个黑色节点的方法数 解法:树形DP问题.定义: dp[u][0]表示以u为根的子树对父亲的贡献为0 dp ...
- codeforces Round #263(div2) D. Appleman and Tree 树形dp
题意: 给出一棵树,每个节点都被标记了黑或白色,要求把这棵树的其中k条变切换,划分成k+1棵子树,每颗子树必须有1个黑色节点,求有多少种划分方法. 题解: 树形dp dp[x][0]表示是以x为根的树 ...
- POJ 2486 Apple Tree(树形DP)
题目链接 树形DP很弱啊,开始看题,觉得貌似挺简单的,然后发现貌似还可以往回走...然后就不知道怎么做了... 看看了题解http://www.cnblogs.com/wuyiqi/archive/2 ...
随机推荐
- UI Recorder安装与使用
现在的互联网公司,普遍在尝试并执行敏捷开发模式,那么必然要涉及到频繁的更新迭代,在每次更新迭代时,老功能的回归成为了老大难.当系统日益复杂,涉及到的回归点逐渐增多,UI自动化测试即使成本在大,也需要提 ...
- springboot + 注解 + 拦截器 + JWT 实现角色权限控制
1.关于JWT,参考: (1)10分钟了解JSON Web令牌(JWT) (2)认识JWT (3)基于jwt的token验证 2.JWT的JAVA实现 Java中对JWT的支持可以考虑使用JJWT开源 ...
- 使用JS实现可断点续传的文件上传方案
需求:项目要支持大文件上传功能,经过讨论,初步将文件上传大小控制在500M内,因此自己需要在项目中进行文件上传部分的调整和配置,自己将大小都以501M来进行限制. 第一步: 前端修改 由于项目使用的是 ...
- 大文件上传-大视频上传,T级别的,求解决方案
第一点:Java代码实现文件上传 FormFile file = manform.getFile(); String newfileName = null; String newpathname = ...
- luogu P1147 连续自然数和 x
P1147 连续自然数和 题目描述 对一个给定的自然数M,求出所有的连续的自然数段,这些连续的自然数段中的全部数之和为M. 例子:1998+1999+2000+2001+2002 = 10000,所以 ...
- 【HDOJ6731】Angle Beats(极角排序)
题意:二维平面上给定n个整点,q个询问 每个询问给定另外的一个整点,问其能与n个整点中任意取2个组成的直角三角形的个数 保证所有点位置不同 n<=2e3,q<=2e3,abs(x[i],y ...
- div的文字倾斜
最近要写一个页面,需要一排文字是倾斜的,我就写了一下 <div class="qingx">倾斜导航</div> div.qingx{ -moz-trans ...
- RedisTemplate访问Redis数据结构(一)——String
当对String数据结构进行操作时,推荐直接使用spring-data-redis提供的StringRedisTemplate,其配置如下 <bean id="stringRedisT ...
- 动态DP总结
动态DP 何为动态DP? 将画风正常的DP加上修改操作. 举个例子? 给你一个长度为\(n\)的数列,从中选出一些数,要求选出的数互不相邻,最大化选出的数的和. 考虑DP,状态设计为\(f[i][1/ ...
- 使用xshell远程连接Linux
Linux系统对于程序员来说并不陌生,对IT技术员来说是一个很好的开发平台,因此掌握Linux系统的操作对于一个程序员来说非常有用.而对于习惯使用windows的人来说直接在Linux系统下进行操作感 ...