• poj1741(树的点分治)


    题目连接:POJ - 1741

    看了好长时间才明白了点......

    网上讲解很多但感觉都不够详细。。。大概是太弱了吧-_-||

    学通了再回来写详解。。。

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<algorithm>
      5 #define LL long long
      6 using namespace std;
      7 const int N=1e5+10;
      8 const int inf=1e9+10;
      9 int n,k;
     10 int rt,ans,sumnode,siz[N],vis[N],d[N];
     11 int dep[N]; //路径长度//dep[0]为子节点个数
     12 int f[N]; //重心
     13 struct edge
     14 {
     15     int v,w,nex;
     16 }e[N*2];
     17 int head[N];
     18 int cnt;
     19 void add(int u,int v,int w)
     20 {
     21     e[cnt].v=v;
     22     e[cnt].w=w;
     23     e[cnt].nex=head[u];
     24     head[u]=cnt++;
     25 }
     26 void getrt(int u,int fa) //找重心
     27 {
     28     siz[u]=1;
     29     f[u]=0;
     30     for(int i=head[u];i!=-1;i=e[i].nex)
     31     {
     32         int v=e[i].v;
     33         if(v==fa||vis[v]) continue;
     34         getrt(v,u);
     35         siz[u]+=siz[v];
     36         f[u]=max(f[u],siz[v]);
     37     }
     38     f[u]=max(sumnode-siz[u],f[u]);
     39     if(f[u]<f[rt]) rt=u;
     40 }
     41 
     42 void getdep(int u,int fa)  //获取子树所有节点与根的距离
     43 {
     44     dep[++dep[0]]=d[u];
     45     for(int i=head[u];i!=-1;i=e[i].nex)
     46     {
     47         int v=e[i].v;
     48         if(v==fa||vis[v]) continue;
     49         d[v]=d[u]+e[i].w;
     50         getdep(v,u);
     51     }
     52 }
     53 
     54 int cal(int u,int now) //计算当前以重心u为根的子树下所有情况的答案
     55 {
     56     d[u]=now;
     57     dep[0]=0;
     58     getdep(u,0);
     59     sort(dep+1,dep+dep[0]+1);
     60     int all=0;
     61     for(int l=1,r=dep[0];l<r;)
     62     {
     63         if(dep[l]+dep[r]<=k) {all+=r-l;l++;}
     64         else r--;
     65     }
     66     return all;
     67 }
     68 
     69 void work(int u) //以u为重心计算
     70 {
     71     vis[u]=1;
     72     ans+=cal(u,0);
     73     for(int i=head[u];i!=-1;i=e[i].nex)
     74     {
     75         int v=e[i].v;
     76         if(vis[v]) continue;
     77         ans-=cal(v,e[i].w);
     78         sumnode=siz[v];
     79         rt=0;
     80         getrt(v,u);
     81         work(rt);
     82     }
     83 }
     84 int u,v,w;
     85 int main()
     86 {
     87     while(scanf("%d%d",&n,&k)!=EOF)
     88     {
     89         if(!n&&!k) break;
     90         memset(head,-1,sizeof(head));
     91         memset(vis,0,sizeof(vis));
     92         cnt=0;
     93         for(int i=0;i<n-1;i++)
     94         {
     95             scanf("%d%d%d",&u,&v,&w);
     96             add(u,v,w);
     97             add(v,u,w);
     98         }
     99         rt=ans=0;
    100         sumnode=n;
    101         f[0]=inf;
    102         getrt(1,0);
    103         work(rt);
    104         printf("%d
    ",ans);
    105     }
    106 }
  • 相关阅读:
    利用fstream进行文件拷贝测试
    gcc下inline的一个问题
    链接选项-rpath的一个问题记录
    OpenCV学习代码记录——人脸检测
    OpenCV学习代码记录—— Snake轮廓
    OpenCV学习代码记录——Hough线段检测
    OpenCV学习代码记录——轮廓(contour)检测
    OpenCV学习代码记录——canny边缘检测
    基于Android平台的会议室管理系统具体设计说明书
    关系型数据库工作原理-事务管理(一)(翻译自Coding-Geek文章)
  • 原文地址:https://www.cnblogs.com/yijiull/p/6803738.html
Copyright © 2020-2023  润新知