1. [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][男人八题]树上的点对(点分治)的更多相关文章

  1. poj 1741 楼教主男人八题之中的一个:树分治

    http://poj.org/problem? id=1741 Description Give a tree with n vertices,each edge has a length(posit ...

  2. poj 1737男人八题之一 orz ltc

    这是楼教主的男人八题之一.很高兴我能做八分之一的男人了. 题目大意:求有n个顶点的连通图有多少个. 解法: 1.  用总数减去不联通的图(网上说可以,我觉得时间悬) 2.    用动态规划(数学递推) ...

  3. POJ1742 Coins(男人八题之一)

    前言 大名鼎鼎的男人八题,终于见识了... 题面 http://poj.org/problem?id=1742 分析 § 1 多重背包 这很显然是一个完全背包问题,考虑转移方程: DP[i][j]表示 ...

  4. 新男人八题---AStringGame

    终于完成进度男人1/8,为了这题学了sam= = 题意先有一个串,n个子串,两个人轮流每次在子串上加字符,要求加完后还是原串的子串,最后不能加的就是输者,求赢的人 解法:sam之后在构造的状态图上跑s ...

  5. poj 1742(好题,楼天城男人八题,混合背包)

    Coins Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 33269   Accepted: 11295 Descripti ...

  6. 博弈论(男人八题):POJ 1740 A New Stone Game

    A New Stone Game Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 5694   Accepted: 3119 ...

  7. poj 1743 男人八题之后缀数组求最长不可重叠最长重复子串

    Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 14874   Accepted: 5118 De ...

  8. nyoj137 取石子(三) 楼教主男人八题之一

    思路:一堆时,N态.两堆时,当两堆数量相同,P态,不同为N态.三堆时,先手可以变成两堆一样的,必胜N态. 此时可以总结规律:堆数为偶数可能且石子数都是两两相同的,为P态.分析四堆时,当四堆中两两数量一 ...

  9. 某模拟赛C题 树上路径统计 (点分治)

    题意 给定一棵有n个节点的无根树,树上的每个点有一个非负整数点权.定义一条路径的价值为路径上的点权和-路径上的点权最大值. 给定参数P,我!=们想知道,有多少不同的树上简单路径,满足它的价值恰好是P的 ...

随机推荐

  1. 解决batik使用JScrollPane显示svg图滚动条不显示的问题

    // 必须使用batik提供的JSVGScrollPane,使用swing自己的组件JScrollPane初始化时滚动条不会显示. JSVGScrollPane svgJScrollPane = ne ...

  2. Qt界面阴影效果(背景图片)

    实现原理: 1.顶层窗体设置为无边框,背景半透明 2.顶层窗体的子窗体使用带有阴影的图片做背景 代码: //CMainWindow.h#ifndef CMAINWINDOW_H#define CMAI ...

  3. AVOSCloud入门教程:Android Parse云服务的Hello World

    本文时间戳:2013年8月30日 AVOSCloud(万象云)才刚刚推出来不久的咯,其背后创业的推动者据说是Youtube的华人老大陈士骏(SteveChen,貌似手头有很多创业,美味,玩拍,都是,开 ...

  4. 关于MQ的几件小事(五)如何保证消息按顺序执行

    1.为什么要保证顺序 消息队列中的若干消息如果是对同一个数据进行操作,这些操作具有前后的关系,必须要按前后的顺序执行,否则就会造成数据异常.举例: 比如通过mysql binlog进行两个数据库的数据 ...

  5. 【转载】常见面试题:C#中String和string的区别分析

    在很多人面试C#开发工程师的时候,会遇到一个面试题,就是C#中String和string有啥区别.其实针对这个问题C#中String和string没有本质上的区别,两者在程序中都可使用,稍微的一个区别 ...

  6. 可以在一个.java文件中写两个类吗?

    一个java文件中可以有任意多个类,接口或是注解..但是只能有一个类是public的,而且这个类的名字要和文件同名,比如public类名为A则文件名就应当为A.java

  7. python 循环结构(for-in)

    循环结构(for-in) 说明:也是循环结构的一种,经常用于遍历字符串.列表,元组,字典等 格式: for x in y: 循环体 执行流程:x依次表示y中的一个元素,遍历完所有元素循环结束 示例1: ...

  8. RZ70注册SLD

    本文的将S4 abap系统向PO JAVA系统中注册. S4 QASERPAP01 NR=60 ASCS=61 PO QASPISAP01 NR=60 SCS=61 http://qaspisap01 ...

  9. 用BIO手写实现Redis客户端的探究(拒绝Jedis)

    在Redis的使用过程中,大多数人都是使用现成的客户端,如Jedis,Redisson,Lettuce.因此本文研究用BIO的方式手写Redis客户端尝试,对遇到的问题进行探究及总结. Redis通讯 ...

  10. unity 刚体

    刚体属性(rigidbody)标明物体受物理影响,包括重力,阻力等等. mass为重量,当大质量物体被小重量物体碰撞时只会发生很小的影响.. Drag现行阻力决定组件在没有发生物理行为下停止移动的速度 ...