COGS1714树上的点对

点分治模板
树上的路径有两种处理方法

一种是拆LCA想办法解决,例如天天爱跑步

另一种就是在重心处统计,这就是点分治

点分治的函数中处理当前节点所在联通块size的时间复杂度必须是O(size)或者O(sizelogsize)

这样点分治的复杂度就可以控制在O(nlogn)和O(nlog2n)

话说为啥不加vis[0]=1就会RE???

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 10010
  4 #define INF (1<<30)
  5 inline int update(int & a,int b){return a>b? a:a=b;}
  6 inline bool isitdigit(char c){ return c<='9'&&c>='0';}
  7 inline int read()
  8 {
  9     register int s,f=1;register char c;
 10     while(!isitdigit(c=getchar())) (c=='-')&&(f=-1);
 11     for(s=c-'0';isitdigit(c=getchar());s=(s<<1)+(s<<3)+c-'0');
 12     return s*f;
 13 }
 14 int n,k;
 15 int head[N],to[N*2],next[N*2],val[N*2],tot;
 16 int mson[N],size[N],root,vis[N];
 17 int deep[N],cnt,res;
 18 inline void add(int f,int t,int v)
 19 {
 20     to[++tot]=t;val[tot]=v;next[tot]=head[f];head[f]=tot;
 21 }
 22 void getroot(int i,int f)
 23 {
 24     mson[i]=0,size[i]=1;
 25     for(register int j=head[i];j;j=next[j]) if(to[j]!=f&&!vis[to[j]])
 26     {
 27         getroot(to[j],i);
 28         update(mson[i],size[to[j]]);
 29         size[i]+=size[to[j]];
 30     }
 31 }
 32 void decideroot(int s,int i,int f)
 33 {
 34     update(mson[i],size[s]-size[i]);
 35     if(mson[root]>=mson[i]) root=i;
 36     for(register int j=head[i];j;j=next[j]) if(to[j]!=f&&!vis[to[j]])
 37         decideroot(s,to[j],i);
 38 }
 39 void getdeep(int i,int f,int d)
 40 {
 41     deep[++cnt]=d;
 42     for(register int j=head[i];j;j=next[j]) if(to[j]!=f&&!vis[to[j]])
 43         getdeep(to[j],i,d+val[j]);
 44 }
 45 inline int work(int i,int d)
 46 {
 47     cnt=0;
 48     getdeep(i,0,d);
 49     //sort(deep+1,deep+cnt+1);
 50     sort(deep+1,deep+cnt+1);
 51     int s=1,t=cnt,ans=0;
 52     while(s<t)
 53     {
 54         while((s<t)&&(deep[s]+deep[t]>k)) 
 55             t--;
 56         ans+=t-s;s++;
 57     }
 58     return ans;
 59 }
 60 void dfs(int i)
 61 {
 62     root=mson[0]=0;
 63     getroot(i,0);
 64     mson[0]=INF;
 65     decideroot(i,i,0);
 66     int ans=work(root,0);
 67     vis[root]=1;
 68     for(register int j=head[root];j;j=next[j]) if(!vis[to[j]])
 69         ans-=work(to[j],val[j]);
 70     res+=ans;
 71     for(register int j=head[root];j;j=next[j]) if(!vis[to[j]])
 72     {
 73         dfs(to[j]);
 74     }
 75 }    
 76 int main()
 77 {
 78     freopen("poj1741_tree.in","r",stdin);
 79     freopen("poj1741_tree.out","w",stdout);
 80     while(scanf("%d%d",&n,&k)&&n&&k)
 81     {    
 82         res=0;
 83         memset(vis,0,sizeof(vis));
 84         memset(head,0,sizeof(head));
 85         memset(to,0,sizeof(to));
 86         memset(next,0,sizeof(next));
 87         memset(val,0,sizeof(val));
 88         tot=0;
 89         vis[0]=1;
 90         for(register int i=1;i<n;++i) 
 91         {
 92             int f=read(),t=read(),v=read();
 93             add(f,t,v);
 94             add(t,f,v);
 95         }
 96         dfs(1);
 97         printf("%d\n",res);
 98     }
 99     return 0;
100 }

猜你喜欢

转载自www.cnblogs.com/MediocreKonjac/p/9138895.html