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的 ...
随机推荐
- 11款航拍辅助APP【转】
盘点丨11款航拍辅助APP_宇辰网_让世界读懂无人机_全球专业无人机资讯|电商|大数据服务平台
- Python完成迪杰斯特拉算法并生成最短路径
def Dijkstra(network,s,d):#迪杰斯特拉算法算s-d的最短路径,并返回该路径和代价 print("Start Dijstra Path……") path=[ ...
- Linux下 sftp服务配置
查看openssh的版本,使用ssh -V 命令来查看openssh的版本,版本必须大于4.8p1,低于的这个版本需要升级. 参考博客:https://yq.aliyun.com/articles/6 ...
- PAT-1021 Deepest Root (25 分) 并查集判断成环和联通+求树的深度
A graph which is connected and acyclic can be considered a tree. The height of the tree depends on t ...
- 在论坛中出现的比较难的sql问题:17(字符分拆2)
原文:在论坛中出现的比较难的sql问题:17(字符分拆2) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. 所以,觉得有必要记录下来 ...
- chrome网页中打开exe
Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\VMS] @="URL:VMS" "URL Protoco ...
- Java帖子
IDEA新手使用教程(详解):https://cloud.tencent.com/developer/article/1448115 Java学习文档:https://www.sxt.cn/Java_ ...
- iOS - error:unrecognized selector sent to class 导入第三方SDK .a后不识别,运行崩溃
今天将app统计的.a静态库包含到一个app应用中,调试时报下面的错误: *** Terminating app due to uncaught exception 'NSInvalidArgumen ...
- 【转载】Sqlserver使用Convert函数进行数据类型转换
在Sqlserver数据库中,可以使用Convert函数来进行数据类型的转换,如将数字类型decimal转换为字符串nvarchar类型,或者将字符串类型转换为数字类型都可以使用Convert函数来实 ...
- 爬虫request库规则与实例
Request库的7个主要方法: requests.request(method,url,**kwargs) method:请求方式,对应get/put/post等7种: r = reques ...