poj 1655:http://poj.org/problem?id=1655

题意: 给无根树,  找出以一节点为根,  使节点最多的树,节点最少。

题解:一道树形dp,先dfs 标记 所有节点的子树的节点数。 再dfs  找出以某节点为根的最大子树,节点最少。 复杂度(n)

/***Good Luck***/
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <stack>
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <functional>
#include <cmath> #define Zero(a) memset(a, 0, sizeof(a))
#define Neg(a) memset(a, -1, sizeof(a))
#define All(a) a.begin(), a.end()
#define PB push_back
#define inf 0x7fffffff
#define inf2 0x7fffffffffffffff
#define ll long long
using namespace std; const int maxn = ;
int n, k, e, head[maxn];
int mx[maxn], sum[maxn], ansn, ansb;
struct Node {
int next, v;
}node[maxn]; void input(int u, int v) {
node[e].next = head[u];
node[e].v = v;
head[u] = e++;
} int dfssize(int b, int fa) {
sum[b] = ;
mx[b] = ;
int tmpmx;
for (int i = head[b]; ~i; i = node[i].next) {
int v = node[i].v;
if (fa != v) {
tmpmx = dfssize(v, b);
sum[b] +=tmpmx;
if (tmpmx > mx[b]) mx[b] = tmpmx;
}
}
return sum[b];
} void solve(int b, int fa) {
int tmpmx;
tmpmx = max(mx[b], n - sum[b]);
if (tmpmx <= ansb) {
if (tmpmx < ansb) {
ansn = b;
ansb = tmpmx;
} else if (b < ansn) {
ansn = b;
ansb = tmpmx;
}
}
for (int i = head[b]; ~i; i = node[i].next) {
int v = node[i].v;
if (fa != v) {
solve(v, b);
}
}
} int main() {
int u, v;
int T;
scanf("%d", &T);
while (T-- ) {
scanf("%d", &n);
e = ;
Neg(head);
for (int i = ; i < n - ; ++i) {
scanf("%d%d", &u, &v);
input(u, v);
input(v, u);
}
dfssize(, );
ansb = inf;
solve(, );
printf("%d %d\n", ansn, ansb);
}
return ;
}

poj 1741:http://poj.org/problem?id=1741

题意:给一值k,在带权无向图G中, 找出两节点相距不大于k的数。

  qzc论文的第一题(膜拜q神  orz),根据论文写的 代码, 先写了一题树形dp(1655),再开始写这的,搞了一晚上具体的还是看论文吧。

找根(n), 计算(logn), 一共执行 logn次  总复杂度(n*logn*logn)

 /***Good Luck***/
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <stack>
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <functional>
#include <cmath> #define Zero(a) memset(a, 0, sizeof(a))
#define Neg(a) memset(a, -1, sizeof(a))
#define All(a) a.begin(), a.end()
#define PB push_back
#define inf 0x3f3f3f3f
#define inf2 0x7fffffffffffffff
#define ll long long
using namespace std;
const int maxn = ;
int head[maxn], n, k, e;
int ans, sum[maxn], mx[maxn];
bool vis[maxn];
int dis[maxn], a[maxn], an;
struct Node {
int w;
int v, next;
}edge[maxn]; void init() {
e = ;
ans = ;
Neg(head);
Zero(vis);
} void add(int u, int v, int w) { //邻接表储存
edge[e].v = v;
edge[e].w = w;
edge[e].next = head[u];
head[u] = e++;
} int dfssize(int u, int fa) { //标记子树的节点数
sum[u] = ;
mx[u] = ;
int tmpmx;
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].v;
if (v != fa && !vis[v]) {
tmpmx = dfssize(v, u);
sum[u] += tmpmx;
if (tmpmx > mx[u]) mx[u] = tmpmx;
}
}
return sum[u];
} int ansn, mxshu;
void find_root(int u, int fa, int nn) { // 找出符合条件的根。
int tmpmx = max(mx[u], nn - sum[u]);
if (tmpmx < mxshu) {
ansn = u;
mxshu = tmpmx;
}
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].v;
if (v != fa && !vis[v]) {
find_root(v, u, nn);
}
}
} void dfsdis(int u, int fa) {
a[an++] = dis[u];
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].v;
if (fa != v && !vis[v]) {
dis[v] = dis[u] + edge[i].w;
dfsdis(v, u);
}
}
} int cal(int u, int fa, int beg) { // 这个方法太神奇了 复杂度只有 (logn)
an = ;
int ret = ;
dis[u] = beg;
dfsdis(u, fa);
sort(a, a + an);
int l = , r = an - ;
while (l < r) {
if (a[r] + a[l] <= k )
ret += r - l++;
else
r--;
}
return ret;
} void solve(int u) {
dfssize(u, );
mxshu = inf;
find_root(u, , sum[u]);
vis[ansn] = true;
ans += cal(ansn, , );
for (int i = head[ansn]; ~i; i = edge[i].next) {
int v = edge[i].v;
if (!vis[v]) {
ans -= cal(v, ansn, edge[i].w);
solve(v);
}
}
}
int main() {
//freopen("data.out", "w", stdout);
//freopen("data.in", "r", stdin);
int u, v, w;
while (scanf("%d%d", &n, &k), n&&k) {
init();
for (int i = ; i < n - ; ++i) {
scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
add(v, u, w);
}
solve();
printf("%d\n", ans);
}
return ;
}

树的点分治 (poj 1741, 1655(树形dp))的更多相关文章

  1. POJ 1741 Tree 树形DP(分治)

    链接:id=1741">http://poj.org/problem?id=1741 题意:给出一棵树,节点数为N(N<=10000),给出N-1条边的两点和权值,给出数值k,问 ...

  2. 点分治——POJ 1741

    写的第一道点分治的题目,权当认识点分治了. 点分治,就是对每条过某个点的路径进行考虑,若路径不经过此点,则可以对其子树进行考虑. 具体可以看menci的blog:点分治 来看一道例题:POJ 1741 ...

  3. Apple Tree POJ - 2486 (树形dp)

    题目链接: D - 树形dp  POJ - 2486 题目大意:一颗树,n个点(1-n),n-1条边,每个点上有一个权值,求从1出发,走V步,最多能遍历到的权值 学习网址:https://blog.c ...

  4. POJ 3107.Godfather 树形dp

    Godfather Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7536   Accepted: 2659 Descrip ...

  5. [POJ 1155] TELE (树形dp)

    题目链接:http://poj.org/problem?id=1155 题目大意:电视台要广播电视节目,要经过中转机构,到观众.从电视台到中转商到观众是一个树形结构,经过一条边需要支付成本.现在给你每 ...

  6. Anniversary party POJ - 2342 (树形DP)

    题目链接:  POJ - 2342 题目大意:给你n个人,然后每个人的重要性,以及两个人之间的附属关系,当上属选择的时候,他的下属不能选择,只要是两个人不互相冲突即可.然后问你以最高领导为起始点的关系 ...

  7. POJ Anniversary party 树形DP

    /* 树形dp: 给一颗树,要求一组节点,节点之间没有父子关系,并且使得所有的节点的权值和最大 对于每一个节点,我们有两种状态 dp[i][0]表示不选择节点i,以节点i为根的子树所能形成的节点集所能 ...

  8. POJ 3342 (树形DP)

    题意 :给出一些上下级关系,要求i和i的直接上级不能同时出现,现在选出一些人构成一个集合,问你这个集合里面的最大人数是都少,同时给出这个最大的人数的集合是否唯一. 思路:树形DP,dp[i][0],表 ...

  9. POJ 2342 (树形DP)

    Anniversary party Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3863   Accepted: 2172 ...

  10. 树分治 poj 1741

    n k n个节点的一棵树 k是距离 求树上有几对点距离<=k; #include<stdio.h> #include<string.h> #include<algo ...

随机推荐

  1. python类的__repr__方法

    python3中的类默认是新式类(继承object类). __repr__()是 Python 类中的一个特殊方法,由于 object 类己提供了该方法, 而所有 的 Python 类都是 objec ...

  2. Java 异常处理的 20 个最佳实践,你知道几个?

    异常处理是 Java 开发中的一个重要部分,是为了处理任何错误状况,比如资源不可访问,非法输入,空输入等等.Java 提供了几个异常处理特性,以try,catch 和 finally 关键字的形式内建 ...

  3. 你好,Go语言

    本文是「vangoleo的Go语言学习笔记」系列文章之一. 官网: http://www.vangoleo.com/go/hello-golang/ 我在2015年第一次接触Go语言,完成了Hello ...

  4. LeetCode刷题笔记(3)Java位运算符与使用按位异或(进制之间的转换)

    1.问题描述 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 算法应该具有线性时间复杂度并且不使用额外空间. 输入: [4,1,2,1,2] 输 ...

  5. unityevent与持续按键触发

    上一篇中提到一种鼠标按下时的事件触发,即采用eventtrigger设定pointerdown和pointerup并绑定相应事件.但是若要实现持续按键则需要对绑定的每个方法都添加实现持续按键方法.所以 ...

  6. day2编程语言发展史

    1.编程语言的发展史: 机器语言 优点:执行速度够快 缺点:开发效率非常低 汇编语言(通过英文字符组成) 优点:执行效率相较于机器语言略低. 缺点:执行效率相较于机器语言略高. 高级语言 c ,c++ ...

  7. Mac高效开发之iTerm2、Prezto和Solarized主题

    本文首发于个人网站:Mac高效开发之iTerm2.Prezto和Solarized主题 工欲善其事必先利其器,作为开发,我追求极致的高效,因此会在很多细节上追求效率,例如:命令行窗口敲命令的时候,如果 ...

  8. django-模板之extends(三)

    /book/base.html <!DOCTYPE html> <html lang="en"> <head> <meta charset ...

  9. pyarango整理

    目录: 连接数据库 创建数据库/集合/文档 检索筛选 更新 删除 调用AQL的方法 安装需要用到的python包: pip install pyarango 一.连接数据库: >>> ...

  10. 前端技术之:使用npx创建一个Nuxt.js项目

    $ npx create-nuxt-app my-first-nuxtjs npx: 401 安装成功,用时 43.891 秒 > Generating Nuxt.js project in / ...