POJ 2114 Boatherds (树上点分治)

题目地址:POJ 2114

点分治水题。只是把距离小于等于k改成了等于k。稍微加一点处理就可以了。

代码如下:

#include <iostream>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <set>
#include <stdio.h>
#include <time.h>
using namespace std;
#define LL __int64
#define pi acos(-1.0)
//#pragma comment(linker, "/STACK:1024000000")
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const double eqs=1e-9;
const int MAXN=20000+10;
int head[MAXN], cnt, tot, tt, min1, n, root;
int siz[MAXN], d[MAXN], dep[MAXN], ans[MAXN], q[MAXN], vis[MAXN];
int c[MAXN], dp[MAXN];
struct node
{
        int v, w, next;
} edge[MAXN<<1];
void add(int u, int v, int w)
{
        edge[cnt].v=v;
        edge[cnt].w=w;
        edge[cnt].next=head[u];
        head[u]=cnt++;
}
void init()
{
        memset(head,-1,sizeof(head));
        cnt=tot=tt=0;
        memset(vis,0,sizeof(vis));
        memset(ans,0,sizeof(ans));
}
void getroot(int u, int fa, int s)
{
        siz[u]=1;
        int max1=0;
        for(int i=head[u];i!=-1;i=edge[i].next){
                int v=edge[i].v;
                if(v==fa||vis[v]) continue ;
                getroot(v,u,s);
                siz[u]+=siz[v];
                max1=max(max1,siz[v]);
        }
        max1=max(max1,s-siz[u]);
        if(min1>max1){
                root=u;
                min1=max1;
        }
}
void getdep(int u, int fa)
{
        d[tot++]=dep[u];
        siz[u]=1;
        for(int i=head[u];i!=-1;i=edge[i].next){
                int v=edge[i].v;
                if(v==fa||vis[v]) continue ;
                dep[v]=dep[u]+edge[i].w;
                getdep(v,u);
                siz[u]+=siz[v];
        }
}
void Cal(int u, int len, int f)
{
        tot=0;
        dep[u]=len;
        getdep(u,-1);
        sort(d,d+tot);
        int i, j, k, y=0;
        c[0]=d[0];
        dp[0]=1;
        for(i=1;i<tot;i++){
                if(d[i]!=d[i-1]){
                        dp[++y]=1;
                        c[y]=d[i];
                }
                else{
                        dp[y]++;
                }
        }
        for(i=0;i<tt;i++){
                k=y;
                for(j=0;j<=y;j++){
                        while(c[j]+c[k]>q[i]&&k>j) k--;
                        if(k==j&&c[j]+c[k]==q[i]) ans[i]+=f*(dp[j]*(dp[j]-1)/2);
                        if(k<=j) break;
                        if(c[j]+c[k]==q[i])  ans[i]+=f*dp[j]*dp[k];
                }
        }
}
void work(int u)
{
        Cal(u,0,1);
        vis[u]=1;
        for(int i=head[u];i!=-1;i=edge[i].next){
                int v=edge[i].v;
                if(vis[v]) continue ;
                Cal(v,edge[i].w,-1);
                min1=INF;
                getroot(v,-1,siz[v]);
                work(root);
        }
}
int main()
{
        int i, v, w, j, x;
        while(scanf("%d",&n)!=EOF&&n){
                init();
                for(i=1;i<=n;i++){
                        while(scanf("%d",&v)!=EOF&&v){
                                scanf("%d",&w);
                                add(i,v,w);
                                add(v,i,w);
                        }
                }
                while(scanf("%d",&x)!=EOF&&x) q[tt++]=x;
                min1=INF;
                getroot(1,-1,n);
                work(root);
                for(i=0;i<tt;i++){
                        if(ans[i]) puts("AYE");
                        else puts("NAY");
                }
                puts(".");
        }
        return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-30 03:35:10

POJ 2114 Boatherds (树上点分治)的相关文章

POJ 2114 Boatherds 树的分治

题目大意:给出一棵树,问有没有两点之间的距离是k的.多组数据 思路:和IOI2011的Race一样,比那个简单.读入太恶心了,我是上网上抄的别人的主函数. CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 10010 #define INF 0x3f3f3f3f using namespace std; int poi

POJ 1741 Tree (树上点分治)(楼教主男人八题之一)

题目地址:POJ 1741 树分治第一发! 树分治详情请看漆子超的国家集训队论文,论文传送门 树分治裸题. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #

POJ 2114 Boatherds

Description Boatherds Inc. is a sailing company operating in the country of Trabantustan and offering boat trips on Trabantian rivers. All the rivers originate somewhere in the mountains and on their way down to the lowlands they gradually join and f

POJ 2114 Boatherds 划分树

标题效果:鉴于一棵树,问有两点之间没有距离是k的. 数据的多组 思维:和IOI2011的Race喜欢.不是这么简单.阅读恶心,我是在主要功能的别人的在线副本. CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 10010 #define INF 0x3f3f3f3f using namespace std; int p

树上点分治 poj 1741

Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dist(u,v)=The min distance between node u and v. Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k. Wri

poj2114 寻找树上存在长度为k点对,树上的分治

寻找树上存在长度为k点对,树上的分治  代码和  这个  差不多 ,改一下判断的就好 #include <iostream> #include <algorithm> #include <cstdio> #include <vector> #include <string.h> using namespace std; const int maxn=10004; int H[maxn],nx[maxn*2],to[maxn*2],numofE,d

poj 1741 树的点分治(入门)

Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 18205   Accepted: 5951 Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dist(u,v)=The min distance between node u and v. Give an

POJ - 1987 Distance Statistics 树上的分治

题目大意:和poj 1741的那题和类似,求树上节点之间的距离小于等于k的节点对有多少对 解题思路:具体可参考:<分治算法在树的路径问题中的应用--漆子超> 给这题的输入坑了,注意输入,不然会超时 #include<cstdio> #include<vector> #include<algorithm> using namespace std; #define maxn 40010 int vis[maxn], Sum[maxn], d[maxn], dp[

POJ 1987 Distance Statistics (树上点分治)

题目地址:POJ 1987 点分治模板题,跟POJ 1741几乎一样,.. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include <stdi