zoukankan      html  css  js  c++  java
  • [BZOJ1316]树上的询问 点分治

    1316: 树上的询问

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1017  Solved: 287
    [Submit][Status][Discuss]

    Description

    一棵n个点的带权有根树,有p个询问,每次询问树中是否存在一条长度为Len的路径,如果是,输出Yes否输出No.

    Input

    第一行两个整数n, p分别表示点的个数和询问的个数. 接下来n-1行每行三个数x, y, c,表示有一条树边x→y,长度为c. 接下来p行每行一个数Len,表示询问树中是否存在一条长度为Len的路径.

    Output

    输出有p行,Yes或No.

    Sample Input

    6 4
    1 2 5
    1 3 7
    1 4 1
    3 5 2
    3 6 3
    1
    8
    13
    14

    Sample Output

    Yes
    Yes
    No
    Yes


    HINT

    30%的数据,n≤100. 
    100%的数据,n≤10000,p≤100,长度≤1000000. 

    做完此题可看下POJ 3237 Tree

    Source

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cstdio>
     5 #include<algorithm>
     6 #include<cmath>
     7 #define maxn 100000
     8 using namespace std;
     9 int n,q;
    10 int ask[maxn];
    11 int ans[maxn];
    12 struct edge {
    13     int to,next,c;
    14 }e[maxn*2];
    15 int head[maxn],cnt;
    16 void add(int u,int v,int c){e[cnt].to=v;e[cnt].next=head[u];e[cnt].c=c;head[u]=cnt++;}
    17 int root;
    18 int vis[maxn],size[maxn],sum,f[maxn];
    19 void findrt(int x,int fa) {
    20     size[x]=1;f[x]=0;
    21     for(int i=head[x];i>=0;i=e[i].next) {
    22         int to=e[i].to;if(to==fa||vis[to]) continue;
    23         findrt(to,x);
    24         size[x]+=size[to];
    25         f[x]=max(f[x],size[to]);
    26     }
    27     f[x]=max(f[x],sum-size[x]);
    28     if(f[x]<f[root]) root=x;
    29 }
    30 int dis[maxn],t[maxn],tt,tmp,num[maxn];
    31 int dfs(int x,int fa,int d) {
    32     dis[++tt]=d;
    33     for(int i=head[x];i>=0;i=e[i].next) {
    34         int to=e[i].to;if(to==fa||vis[to]) continue;
    35         dfs(to,x,d+e[i].c);
    36     }
    37 }
    38 void cal(int x,int fl,int d) {
    39     tt=0;tmp=0;
    40     dfs(x,0,d);
    41     sort(dis+1,dis+tt+1);
    42     for(int i=1;i<=tt;i++) {
    43         if(dis[i]!=dis[i-1]||i==1) dis[++tmp]=dis[i],num[tmp]=1;
    44         else num[tmp]++;
    45     }
    46     for(int i=1;i<=q;i++) {
    47         for(int j=1;j<=tmp;j++)
    48             if(num[j]>=2&&dis[j]*2==ask[i]) ans[i]+=fl*num[j]*(num[j]-1);
    49         int l=1,r=tmp;
    50         while(l<r) {
    51             if(dis[l]+dis[r]>ask[i]&&l<r) r--;
    52             else {
    53                 if(dis[l]+dis[r]==ask[i]) ans[i]+=fl*num[l]*num[r];
    54                 l++;
    55             }
    56         }
    57     }
    58     
    59 }
    60 void work(int x) {
    61     vis[x]=1;cal(x,1,0);
    62     for(int i=head[x];i>=0;i=e[i].next) {
    63         int to=e[i].to;if(vis[to]) continue;
    64         cal(to,-1,e[i].c);
    65         root=0;sum=size[to];findrt(to,x);
    66         work(root);
    67     }
    68 }
    69 int main() {
    70     memset(head,-1,sizeof(head));
    71     scanf("%d%d",&n,&q);
    72     for(int i=1;i<n;i++) {
    73         int a,b,c;
    74         scanf("%d%d%d",&a,&b,&c);
    75         add(a,b,c);add(b,a,c);
    76     }
    77     for(int i=1;i<=q;i++) scanf("%d",&ask[i]);
    78     f[0]=2147483647;sum=n;
    79     findrt(1,0);
    80     work(root);
    81     for(int i=1;i<=q;i++)
    82         if(ans[i]>0||!ask[i]) printf("Yes
    ");
    83         else printf("No
    ");
    84 }
    View Code
    O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~
  • 相关阅读:
    WPF中调用资源字典的方法
    DataGridView控制单元格修改的输入规则
    将dataGridView数据转成DataTable
    窗体打开后设置某个控件为默认的焦点
    自定义控件属性英文类别
    VMWare虚拟机与主机建立共享文件夹
    与.Net大师Jeffrey Richter面对面交流——TUP对话大师系列活动回顾(多图配详细文字)
    一个编程小题目引发的思考(下)
    一个Quicksort究竟可以写到多么短
    我是如何设计并实现一门程序设计语言——一门函数式编程语言Lucida的诞生
  • 原文地址:https://www.cnblogs.com/wls001/p/8480482.html
Copyright © 2011-2022 走看看