树的点分治 (poj 1741, 1655(树形dp))
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))的更多相关文章
- POJ 1741 Tree 树形DP(分治)
链接:id=1741">http://poj.org/problem?id=1741 题意:给出一棵树,节点数为N(N<=10000),给出N-1条边的两点和权值,给出数值k,问 ...
- 点分治——POJ 1741
写的第一道点分治的题目,权当认识点分治了. 点分治,就是对每条过某个点的路径进行考虑,若路径不经过此点,则可以对其子树进行考虑. 具体可以看menci的blog:点分治 来看一道例题:POJ 1741 ...
- Apple Tree POJ - 2486 (树形dp)
题目链接: D - 树形dp POJ - 2486 题目大意:一颗树,n个点(1-n),n-1条边,每个点上有一个权值,求从1出发,走V步,最多能遍历到的权值 学习网址:https://blog.c ...
- POJ 3107.Godfather 树形dp
Godfather Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 7536 Accepted: 2659 Descrip ...
- [POJ 1155] TELE (树形dp)
题目链接:http://poj.org/problem?id=1155 题目大意:电视台要广播电视节目,要经过中转机构,到观众.从电视台到中转商到观众是一个树形结构,经过一条边需要支付成本.现在给你每 ...
- Anniversary party POJ - 2342 (树形DP)
题目链接: POJ - 2342 题目大意:给你n个人,然后每个人的重要性,以及两个人之间的附属关系,当上属选择的时候,他的下属不能选择,只要是两个人不互相冲突即可.然后问你以最高领导为起始点的关系 ...
- POJ Anniversary party 树形DP
/* 树形dp: 给一颗树,要求一组节点,节点之间没有父子关系,并且使得所有的节点的权值和最大 对于每一个节点,我们有两种状态 dp[i][0]表示不选择节点i,以节点i为根的子树所能形成的节点集所能 ...
- POJ 3342 (树形DP)
题意 :给出一些上下级关系,要求i和i的直接上级不能同时出现,现在选出一些人构成一个集合,问你这个集合里面的最大人数是都少,同时给出这个最大的人数的集合是否唯一. 思路:树形DP,dp[i][0],表 ...
- POJ 2342 (树形DP)
Anniversary party Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 3863 Accepted: 2172 ...
- 树分治 poj 1741
n k n个节点的一棵树 k是距离 求树上有几对点距离<=k; #include<stdio.h> #include<string.h> #include<algo ...
随机推荐
- 在Hadoop上用Python实现WordCount
一.简单说明 本例中我们用Python写一个简单的运行在Hadoop上的MapReduce程序,即WordCount(读取文本文件并统计单词的词频).这里我们将要输入的单词文本input.txt和Py ...
- 异步IO实例
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> ...
- Knative 实战:基于 Kafka 实现消息推送
作者 | 元毅 阿里云智能事业群高级开发工程师 导读:当前在 Knative 中已经提供了对 Kafka 事件源的支持,那么如何基于 Kafka 实现消息推送呢?本文作者将以阿里云 Kafka 产品为 ...
- mysql库表优化实例
一.SQL优化 1.优化SQL一般步骤 1.1 查看SQL执行频率 SHOW STATUS LIKE 'Com_%'; Com_select:执行SELECT操作的次数,一次查询累加1.其他类似 以下 ...
- 设计模式(十四)Chain of Responsibility模式
Chain of Responsibility模式就是当外部请求程序进行某个处理,但程序暂时无法直接决定由哪个对象负责处理时,就需要推卸责任.也就是说,当一个人被要求做什么事时,如果他可以做就自己做, ...
- django-Views之使用视图渲染模板(五)
render(<request>,<template_name>,context=-None,content_type=None,status=None,using=None) ...
- python的GIL锁
进程:系统运行的一个程序,是系统分配资源的基本单位. 线程:是进程中执行运算的最小单位,是处理机调度的基本单位. 处理机:是计算机中存储程序和数据,并按照程序规定的步骤执行指令的部件.包括中央处理器. ...
- PCES - alpha阶段测试报告
测试计划 测试目的 本测试目的在于测试项目完成情况,以及分析测试结果,为下一轮开发提供解决方案 测试项目 学生用户登录测试 课程信息检索测试 服务器测试 在测试过程中出现的Bug 用户界面间的跳转逻辑 ...
- 汇编语言——物理地址=段地址x16+偏移地址,检测点2.2
一.为什么 物理地址=段地址x16+偏移地址? 刚开始学时,我都笨到不明白为什么是2的N次方,咱把物理地址就当数字,计算机中数字是由很多位0或1自由组合的, 而每一位上要么是0要么是1,只有这两种情况 ...
- abp(net core)+easyui+efcore实现仓储管理系统——EasyUI之货物管理七(二十五)
abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统——ABP总体介绍(一) abp(net core)+ ...