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. Spring Boot Security And JSON Web Token

    Spring Boot Security And JSON Web Token 说明 流程说明 何时生成和使用jwt,其实我们主要是token更有意义并携带一些信息 https://github.co ...

  2. [线段树系列] LCT打延迟标记的正确姿势

    这一篇博客将教你什么? 如何用LCT打延迟标记,LCT和线段树延迟标记间的关系,为什么延迟标记要这样打. ——正片开始—— 学习这一篇博客前,确保你会以下知识: Link-Cut-Tree,普通线段树 ...

  3. 使用jquery插件uploadfive、jcrop实现头像上传

    1.html页面部分代码:(实现选着图片时,jcrop能够刷新图片) <script type="text/javascript"> $(function(){ $(& ...

  4. 使用 Django 项目中的 ORM 编写伪造测试数据脚本

    作者:HelloGitHub-追梦人物 文中所涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 为了防止博客首页展示的文章过多以及提升加载速度,可以对文章列表进行分页展示.不过这需 ...

  5. 设计模式(十)Strategy模式

    Strategy模式,就是用来整体地替换算法,可以轻松地以不同的算法解决同一个问题. 还是根据一个示例程序来理解这种设计模式吧.先看一下示例程序的类图. 然后看示例程序代码. package bigj ...

  6. StackView在Android的应用

    StackView是AdapterViewAnimator的子类,它用于显示Adapter提供的一系列View.StackView将会以“堆叠”的方式来显示多个列表项.为了控制StackView现实的 ...

  7. 本地客户端(自己的电脑)连接远程Oracle数据库(服务器端),客户端安装步骤

    如果本地自己的电脑没有安装Oracle(服务器端数据库),那就要单独安装HA-Instant Client-v11.2.0.3.0.exe(oracle_client客户端) 如果本地安装了Oracl ...

  8. 【C#多线程】1.Thread类的使用及注意要点

    Thread随便讲讲 因为在C#中,Thread类在我们的新业务上并不常用了(因为创建一个新线程要比直接从线程池拿线程更加耗费资源),并且在.NET4.0后新增了Task类即Async与await关键 ...

  9. Go语言入门:Hello world

    本文是「vangoleo的Go语言学习笔记」系列文章之一. 官网: http://www.vangoleo.com/go/go-hello-world/ 在上一篇文章你好,Go语言中,我们对Go语言的 ...

  10. MYSQL-LINUX 安装步骤

    https://www.cnblogs.com/dengshihuang/p/8029092.html   5.7版本安装步骤 1.官网下载mysql二进制文件,匹配自己的linux版本: wget ...