• 点分治练习: boatherds


    【题面】

    求一颗树上距离为K的点对是否存在

    输入数据

    n,m

    接下来n-1条边a,b,c描述a到b有一条长度为c的路径

    接下来m行每行询问一个K

    输出数据

    对于每个K每行输出一个答案,存在输出“AYE”,否则输出”NAY”(不包含引号)

    数据范围

    对于30%的数据n<=100

    对于60%的数据n<=1000,m<=50

    对于100%的数据n<=10000,m<=100,c<=1000,K<=10000000

    【思路】

           树分治。

           离线存储m个询问。分治判断该m个询问是否能够出现。

           具体操作:假设当前处理第S个子树,exist[]中存储着前S-1棵子树中出现过的dis,一遍dfs得到S子树的所有dis,并判断m个询问。

           时间复杂度为O(nmlogn)

           别放了exist[0] <- 0和清空exist就好了QAQ

    【代码】

     1 #include<cstdio>
     2 #include<vector>
     3 #include<queue>
     4 #include<cstring>
     5 #include<iostream>
     6 #include<algorithm>
     7 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
     8 using namespace std;
     9 
    10 const int N = 1e4+10;
    11 const int M = 1e7+10;
    12 
    13 struct Edge {
    14     int v,w;
    15     Edge(int v=0,int w=0) :v(v),w(w){}
    16 };
    17 vector<Edge> g[N];
    18 int n,m,k,q[N],ans[N];
    19 int root,size,siz[N],f[N],dis[N],vis[N],tmp[N],l1,l2,exist[M];
    20 
    21 void getroot(int u,int fa) {
    22     siz[u]=1; f[u]=0; exist[0]=1;
    23     for(int i=0;i<g[u].size();i++) {
    24         int v=g[u][i].v;
    25         if(v!=fa && !vis[v]) {
    26             getroot(v,u);
    27             siz[u]+=siz[v];
    28             if(siz[v]>f[u]) f[u]=siz[v];
    29         }
    30     }
    31     f[u]=max(f[u],size-siz[u]);
    32     if(f[u]<f[root]) root=u;
    33 }
    34 void dfs(int u,int fa) {
    35     tmp[++l1]=dis[u];
    36     for(int i=0;i<g[u].size();i++) {
    37         int v=g[u][i].v;
    38         if(v!=fa && !vis[v]) {
    39             dis[v]=dis[u]+g[u][i].w;
    40             dfs(v,u);
    41         }
    42     }
    43 }
    44 void solve(int u) {
    45     vis[u]=1;
    46     l1=l2=0;
    47     for(int i=0;i<g[u].size();i++) {
    48         int v=g[u][i].v;
    49         l2=l1+1;
    50         if(!vis[v]) {
    51             dis[v]=g[u][i].w;
    52             dfs(v,u);
    53             FOR(i,l2,l1) FOR(j,1,m) 
    54                 if(q[j]>=tmp[i] && exist[q[j]-tmp[i]]) ans[j]=1;
    55             FOR(i,l2,l1) exist[tmp[i]]=1;
    56         }
    57     }
    58     FOR(i,1,l1) exist[tmp[i]]=0;
    59     for(int i=0;i<g[u].size();i++) {
    60         int v=g[u][i].v;
    61         if(!vis[v]) {
    62             root=0; getroot(u,-1);
    63             size=siz[v]; solve(root);
    64         }
    65     }
    66 }
    67 
    68 void read(int& x) {
    69     char c=getchar(); int f=1; x=0;
    70     while(!isdigit(c)){if(c=='-') c=-1; c=getchar();}
    71     while(isdigit(c)) x=x*10+c-'0',c=getchar();
    72     x*=f;
    73 }
    74 int main() {
    75     //freopen("in.in","r",stdin);
    76     //freopen("out.out","w",stdout);
    77     read(n),read(m);
    78     int u,v,w;
    79     FOR(i,1,n-1) {
    80         read(u),read(v),read(w);
    81         g[u].push_back(Edge(v,w));
    82         g[v].push_back(Edge(u,w));
    83     }
    84     FOR(i,1,m) read(q[i]);
    85     size=n; f[0]=1e9; root=0;
    86     getroot(1,-1); solve(root);
    87     FOR(i,1,m) if(ans[i]) puts("AYE"); else puts("NAY");
    88     return 0;
    89 }
  • 相关阅读:
    PHP学习当中遗漏的知识点
    sql必知必会(第四版) 学习笔记
    servlet 笔记
    sql server 快捷键
    233
    第 四 课 数据类型
    第三课 go语言基础语法
    第二课 go语言的结构
    第 1 课 Go 简介
    linux 学习 查看文件占用空间大小
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5188352.html
Copyright © 2020-2023  润新知