Cogs 1714. [POJ1741][男人八题]树上的点对(点分治)
- [POJ1741][男人八题]树上的点对
★★★ 输入文件:poj1741_tree.in 输出文件:poj1741_tree.out 简单对比
时间限制:1 s 内存限制:256 MB
【题目描述】
给一棵有n个节点的树,每条边都有一个长度(小于1001的正整数)。
定义dist(u,v)=节点u到节点v的最短路距离。
给出一个整数k,我们称顶点对(u,v)是合法的当且仅当dist(u,v)不大于k。
写一个程序,对于给定的树,计算有多少对顶点对是合法的。
【输入格式】
输入包含多组数据。
每组数据的第一行有两个整数N,K(N<=10000)。接下来N-1行每行有三个整数u,v,l,代表节点u和v之间有一条长度l的无向边。
输入结束标志为N=K=0.
【输出格式】
对每组数据输出一行一个正整数,即合法顶点对的数量。
【样例输入】
5 4
1 2 3
1 3 1
1 4 2
3 5 1
0 0
【样例输出】
8
【来源】
**POJ 1741 Tree
男人八题 Problem E**
/*
乱搞80分2333.
T了.
处理出每个树的贡献,再减去在每颗子树中的贡献.
可能是让链卡掉了QWQ.
每个点至多有logn个父亲.
也就是在logn个子树中.
复杂度应该是O(Nlogn2)的.
如果是链的话就变成了O(N^2).
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define MAXN 10001
using namespace std;
int n,k,tot,ans,cut,dis[MAXN],maxsize,s[MAXN],a[MAXN],pos[MAXN],end[MAXN],fa[MAXN],head[MAXN],deep[MAXN],size[MAXN];
struct edge{int v,next,x;}e[MAXN*2];
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
return x*f;
}
void add(int u,int v,int x)
{
e[++cut].v=v;e[cut].x=x;e[cut].next=head[u];head[u]=cut;
}
void dfs(int u)
{
s[++maxsize]=dis[u];pos[u]=maxsize;
for(int i=head[u];i;i=e[i].next)
{
if(!fa[e[i].v])
deep[e[i].v]=deep[u]+1,
fa[e[i].v]=u,dis[e[i].v]=dis[u]+e[i].x,dfs(e[i].v);
}
end[u]=maxsize;
return ;
}
int erfen(int l,int r)
{
int total=0;
while(l<r)
{
if(a[l]+a[r]<=k) total+=r-l,l++;
else r--;
}
return total;
}
int get(int u,int d)
{
int sum=0;tot=0;
for(int i=pos[u];i<=end[u];i++) a[++tot]=s[i]-dis[u]+d;
sort(a+1,a+tot+1);
return erfen(1,tot);
}
void get_dis(int u)
{
ans+=get(u,0);
for(int i=head[u];i;i=e[i].next)
if(fa[e[i].v]==u) ans-=get(e[i].v,e[i].x),get_dis(e[i].v);
return ;
}
void slove()
{
fa[1]=1;dfs(1);
for(int i=1;i<=n;i++) a[i]=s[i];
sort(a+1,a+n+1);
ans+=erfen(1,n);
for(int i=head[1];i;i=e[i].next)
if(fa[e[i].v]==1) ans-=get(e[i].v,e[i].x),get_dis(e[i].v);
return ;
}
void Clear()
{
memset(head,0,sizeof head);
memset(fa,0,sizeof fa);
cut=maxsize=tot=ans=0;
}
int main()
{
freopen("poj1741_tree.in","r",stdin);
freopen("poj1741_tree.out","w",stdout);
int x,y,z;
while(true)
{
Clear();n=read(),k=read();
if(!n&&!k) break;
for(int i=1;i<=n-1;i++)
{
x=read(),y=read(),z=read();
add(x,y,z),add(y,x,z);
}
slove();
printf("%d\n",ans);
}
return 0;
}
/*
点分治.
找树的重心.
第一次打,抄的黄学长的.
重心是使得与该点相邻的联通块点数
最大的最小化的那个点.
显然如果用一颗树的重心作根的话,
可以使子树最大的最小化.
复杂度应该是O(Nlogn2)的.
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define MAXN 10001
using namespace std;
int n,k,tot,ans,cut,f[MAXN],sum,root,dis[MAXN],maxsize,a[MAXN],head[MAXN],deep[MAXN],size[MAXN];
bool b[MAXN];
struct edge{int v,next,x;}e[MAXN*2];
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
return x*f;
}
void add(int u,int v,int x)
{
e[++cut].v=v;e[cut].x=x;e[cut].next=head[u];head[u]=cut;
}
int erfen(int l,int r)
{
int total=0;
while(l<r)
{
if(a[l]+a[r]<=k) total+=r-l,l++;
else r--;
}
return total;
}
void get_root(int u,int fa)
{
size[u]=1;f[u]=0;
for(int i=head[u];i;i=e[i].next)
{
if(e[i].v==fa||b[e[i].v]) continue;
get_root(e[i].v,u);
size[u]+=size[e[i].v];
f[u]=max(f[u],size[e[i].v]);
}
f[u]=max(f[u],sum-size[u]);//u上方的联通块.
if(f[u]<f[root]) root=u;
}
void get_deep(int u,int fa)
{
a[++tot]=dis[u];
for(int i=head[u];i;i=e[i].next)
{
if(e[i].v==fa||b[e[i].v]) continue;
dis[e[i].v]=dis[u]+e[i].x;
get_deep(e[i].v,u);
}
return ;
}
int get(int u,int d)
{
dis[u]=d;tot=0;
get_deep(u,0);
sort(a+1,a+tot+1);
return erfen(1,tot);
}
void slove(int u)
{
b[u]=true;ans+=get(u,0);
for(int i=head[u];i;i=e[i].next)
{
if(b[e[i].v]) continue;
ans-=get(e[i].v,e[i].x);
sum=size[e[i].v];
root=0;
get_root(e[i].v,root);
slove(root);
}
return ;
}
void Clear()
{
memset(head,0,sizeof head);
memset(b,0,sizeof b);
memset(f,0,sizeof f);
root=cut=maxsize=tot=ans=0;
}
int main()
{
freopen("poj1741_tree.in","r",stdin);
freopen("poj1741_tree.out","w",stdout);
int x,y,z;
while(true)
{
Clear();n=read(),k=read();
if(!n&&!k) break;
for(int i=1;i<=n-1;i++)
{
x=read(),y=read(),z=read();
add(x,y,z),add(y,x,z);
}
f[0]=1e9;
sum=n,get_root(1,root);
slove(root);
printf("%d\n",ans);
}
return 0;
}
Cogs 1714. [POJ1741][男人八题]树上的点对(点分治)的更多相关文章
- poj 1741 楼教主男人八题之中的一个:树分治
http://poj.org/problem? id=1741 Description Give a tree with n vertices,each edge has a length(posit ...
- poj 1737男人八题之一 orz ltc
这是楼教主的男人八题之一.很高兴我能做八分之一的男人了. 题目大意:求有n个顶点的连通图有多少个. 解法: 1. 用总数减去不联通的图(网上说可以,我觉得时间悬) 2. 用动态规划(数学递推) ...
- POJ1742 Coins(男人八题之一)
前言 大名鼎鼎的男人八题,终于见识了... 题面 http://poj.org/problem?id=1742 分析 § 1 多重背包 这很显然是一个完全背包问题,考虑转移方程: DP[i][j]表示 ...
- 新男人八题---AStringGame
终于完成进度男人1/8,为了这题学了sam= = 题意先有一个串,n个子串,两个人轮流每次在子串上加字符,要求加完后还是原串的子串,最后不能加的就是输者,求赢的人 解法:sam之后在构造的状态图上跑s ...
- poj 1742(好题,楼天城男人八题,混合背包)
Coins Time Limit: 3000MS Memory Limit: 30000K Total Submissions: 33269 Accepted: 11295 Descripti ...
- 博弈论(男人八题):POJ 1740 A New Stone Game
A New Stone Game Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 5694 Accepted: 3119 ...
- poj 1743 男人八题之后缀数组求最长不可重叠最长重复子串
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 14874 Accepted: 5118 De ...
- nyoj137 取石子(三) 楼教主男人八题之一
思路:一堆时,N态.两堆时,当两堆数量相同,P态,不同为N态.三堆时,先手可以变成两堆一样的,必胜N态. 此时可以总结规律:堆数为偶数可能且石子数都是两两相同的,为P态.分析四堆时,当四堆中两两数量一 ...
- 某模拟赛C题 树上路径统计 (点分治)
题意 给定一棵有n个节点的无根树,树上的每个点有一个非负整数点权.定义一条路径的价值为路径上的点权和-路径上的点权最大值. 给定参数P,我!=们想知道,有多少不同的树上简单路径,满足它的价值恰好是P的 ...
随机推荐
- 海思HI35xx平台软件开发快速入门之H264解码实例学习
ref :https://blog.csdn.net/wytzsjzly/article/details/82500277 前言 H264视频编码技术诞生于2003年,至今已有十余载,技术相当成熟 ...
- 使用UltraISO制作Centos7 U盘启动盘遇到的坑
下载.安装UltraISO软件 安装好以后,打开软件 击菜单栏的"文件"选项,再点击"打开"按钮,选择要刻录的系统镜像 点击菜单栏的"启动" ...
- 天梯赛 L3-002. 堆栈
思路:这里的线段树维护一个区间里面出现数的个数,对于Pop,push单点更新一下就好. #include<stdio.h> #include<iostream> #includ ...
- css 盒子 取值
盒子:当我们设置一个标签宽高时,默认设置的是盒子里面content大小. 内容盒:content 填充盒:content+padding(overflow截取的区域) 边框盒:content+padd ...
- table固定宽度与自动宽度
table-layout:auto(创建的table默认是此布局模式): 对table和td.th指定的宽度无效,浏览器会计算所有单元格的内容宽度才能得出一列宽度 如果想对单元格的内容自动折行需使用w ...
- H5之拖拽
步骤: 1.为将要拖拽的元素设置允许拖拽,并赋予dragstart事件将其id转换成数据保存: 2.为容器添加dragover属性添加事件阻止浏览器默认事件,允许元素放置,并赋予drop事件进行元素的 ...
- Fortify漏洞之Sql Injection(sql注入)
公司最近启用了Fortify扫描项目代码,报出较多的漏洞,安排了本人进行修复,近段时间将对修复的过程和一些修复的漏洞总结整理于此! 本篇先对Fortify做个简单的认识,同时总结一下sql注入的漏洞! ...
- stm32 SPI-FLASH W25Q64
The W25Q64BV array is organized into 32,768 programmable pages of 256-bytes each. Up to 256 bytes ca ...
- volatile和锁
让编译器不要将变量缓存到寄存器,而是每次去访问主板上的内存 可见性 对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入 原子性 对任意单个volatile变量的 ...
- vue父子组件传值例子
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...