• 【POJ】【1741】/【BZOJ】【1468】Tree


    点分治


    怎么又一道叫Tree的题目……真是醉了。

    本题为漆子超论文《分治算法在树的路径问题中的应用》例一

    题解 : http://blog.csdn.net/sdj222555/article/details/7893862

           http://blog.csdn.net/yang_7_46/article/details/9966455

      既然是点分治嘛,为了保证复杂度不退化,必然要找树的重心,这一步可以通过一次dfs实现:以任意节点为根(方便起见就选1号节点了)求出每个节点子树大小,那么当前节点就将整棵树分为size[x],n-size[x]两部分,我们取较大的那一部分作为当前节点的子树大小(只是记录个值而已, 不必在意具体哪个是根),然后我们可以在dfs到每个节点时与全局变量root比较一下 f[x]和f[root] 如果f[x]<f[root] 则root=x(这里用root表示重心)(由于f[x]>=n/2,所以f[x]最小的那个x就是将整棵树分的最平均的那个“重心”)

      找到重心后,需要统计所有点(n-1个)到重心的距离,统计有多少对点之间的距离小于等于k。同样用一次dfs实现,然后将所有节点到重心的距离存在一个数组里,进行一次快排~然后利用单调性,一次相向搜索在O(n)时间内解决。但是这是有额外计数的:两点在同一子树里的是不能算的,所以减去两点在同一子树里的情况(递归求解子树的时候会再算一次)。当然还是要递归算各子树内的点对啦~

     1 //POJ 1741
     2 #include<cstdio>
     3 #include<vector>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<iostream>
     7 #include<algorithm>
     8 #define rep(i,n) for(int i=0;i<n;++i)
     9 #define F(i,j,n) for(int i=j;i<=n;++i)
    10 #define D(i,j,n) for(int i=j;i>=n;--i)
    11 #define pb push_back
    12 using namespace std;
    13 void read(int &v){
    14     v=0; int sign=1; char ch=getchar();
    15     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
    16     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
    17     v*=sign;
    18 }
    19 /******************tamplate*********************/
    20 const int N=10086;
    21 struct edge{
    22     int to,l;
    23 };
    24 int n,k,size,s[N],f[N],root,d[N],ans,K;
    25 vector<edge>G[N];
    26 vector<int>dep;
    27 bool vis[N];
    28 
    29 void getroot(int x,int fa){
    30     int y;
    31     s[x]=1;f[x]=0;
    32     rep(i,G[x].size()){
    33         y=G[x][i].to;
    34         if (y!=fa && !vis[y]){
    35             getroot(y,x);
    36             s[x]+=s[y];
    37             f[x]=max(f[x],s[y]);
    38         }
    39     }
    40     f[x]=max(f[x],size-s[x]);
    41     if (f[x]<f[root]) root=x;
    42 }
    43 void getdep(int x,int fa){
    44     int y;
    45     dep.pb(d[x]);
    46     s[x]=1;
    47     rep(i,G[x].size()){
    48         y=G[x][i].to;
    49         if (y!=fa && !vis[y]){
    50             d[y]=d[x]+G[x][i].l;
    51             getdep(y,x);
    52             s[x]+=s[y];
    53         }
    54     }
    55 }
    56 int calc(int x,int init){
    57     dep.clear(); d[x]=init;
    58     getdep(x,0);
    59     sort(dep.begin(),dep.end());
    60     int ans=0;
    61     for(int l=0,r=dep.size()-1; l<r; )
    62         if (dep[l]+dep[r]<=k) ans+=r-l++;
    63         else r--;
    64     return ans;
    65 }
    66 void work(int x){
    67     int y;
    68     ans+=calc(x,0);
    69     vis[x]=1;
    70     rep(i,G[x].size()){
    71         y=G[x][i].to;
    72         if (!vis[y]){
    73             ans-=calc(y,G[x][i].l);
    74             f[0]=size=s[y];
    75             getroot(y,root=0);
    76             work(root);
    77         }
    78     }
    79 }
    80 int main(){
    81 //    freopen("1741.in","r",stdin);
    82     while(scanf("%d%d",&n,&k)==2){
    83         if (n==0 && K==0) break;
    84         int x,y,z;
    85         F(i,1,n) G[i].clear();
    86         memset(vis,0,sizeof vis);
    87         F(i,2,n){
    88             read(x); read(y); read(z);
    89             G[x].pb((edge){y,z}); G[y].pb((edge){x,z});
    90         }
    91         f[0]=size=n;
    92         getroot(1,root=0);
    93         ans=0;
    94         work(root);
    95         printf("%d
    ",ans);
    96     }
    97     return 0;
    98 }
    View Code

    1468: Tree

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 606  Solved: 317
    [Submit][Status][Discuss]

    Description

    给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K

    Input

    N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是k

    Output

    一行,有多少对点之间的距离小于等于k

    Sample Input

    7
    1 6 13
    6 3 9
    3 5 7
    4 1 3
    2 4 20
    4 7 2
    10

    Sample Output

    5

    HINT

    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    统计图配色方案_填充
    如何在C/S下打印报表
    如何利用API导出带有页眉页脚的excel
    通过ajax记录打印信息
    reportConfig.xml两种数据源连接的配置方式
    润乾填报页面导入excel后增加js动作
    matplotlib多plot可视化
    Python之SGDRegressor
    Python之岭回归
    Python之随机梯度下降
  • 原文地址:https://www.cnblogs.com/Tunix/p/4235067.html
Copyright © 2020-2023  润新知