zoukankan      html  css  js  c++  java
  • POJ 1741/1987 树的点分治

    树的点分治,主要思想是每次找子树的重心,计算经过根节点的情况数,再减去点对属于同一子树的情况。

      1 #include <iostream>
      2 #include <vector>
      3 #include <algorithm>
      4 #include <string>
      5 #include <string.h>
      6 #include <stdio.h>
      7 #include <stdlib.h>
      8 #include <queue>
      9 #include <stack>
     10 #include <map>
     11 #include <set>
     12 #include <cmath>
     13 #include <ctime>
     14 #include <cassert>
     15 #include <sstream>
     16 using namespace std;
     17 
     18 const int N=10010;
     19 struct Edge {
     20     int to,next;
     21     int w;
     22     Edge(){}
     23     Edge (int _t,int _n,int _w=0) {
     24         to=_t;
     25         next=_n;
     26         w=_w;
     27     }
     28 }edge[N<<1];
     29 int idx,head[N];
     30 void addEdge (int u,int v,int w) {
     31     ++idx;
     32     edge[idx]=Edge(v,head[u],w);
     33     head[u]=idx;
     34 }
     35 bool vis[N];
     36 
     37 int K;// 输入中的k
     38 
     39 int dis[N],disCnt;
     40 void getDis(int u,int f,int d) {
     41     dis[disCnt++]=d;
     42     for (int k=head[u];k;k=edge[k].next) {
     43         int v=edge[k].to;
     44         if (vis[v]||v==f) continue;
     45         getDis(v,u,d+edge[k].w);
     46     }
     47 }
     48 
     49 int bal,cmp;
     50 int getBal(int u,int f) {
     51     int son=1;
     52     int dp=0;
     53     for (int k=head[u];k;k=edge[k].next) {
     54         int v=edge[k].to;
     55         if (vis[v]||v==f) continue;
     56         int subSon=getBal(v,u);
     57         son+=subSon;
     58         dp=max(dp,subSon);
     59     }
     60     dp=max(dp,disCnt-son);
     61     if (dp<cmp){
     62         cmp=dp;
     63         bal=u;
     64     }
     65     return son;
     66 }
     67 
     68 int calc(int u,int initDis) {
     69     disCnt=0;
     70     getDis(u,-1,initDis);
     71     sort(dis,dis+disCnt);
     72     int ret=0;
     73     int l=0,r=disCnt-1;
     74     while (l<r) {
     75         if (dis[l]+dis[r]>K) r--;
     76         else ret+=r-l++;
     77     }
     78     return ret;
     79 }
     80 
     81 int ans=0;
     82 void solve(int u) {
     83     cmp=~0U>>1;
     84     getBal(u,-1);
     85     ans+=calc(bal,0);
     86     vis[bal]=true;
     87     for (int k=head[bal];k;k=edge[k].next) {
     88         int v=edge[k].to;
     89         if (vis[v]) continue;
     90         ans-=calc(v,edge[k].w);// 减去子树内的重复计算的情况
     91         solve(v);
     92     }
     93 }
     94 
     95 void init(int n) {
     96     idx=1;memset(head,0,sizeof head);
     97     memset(vis,false,sizeof vis);
     98     disCnt=n;// 由于在计算重心时,可以直接用之前算dis时的disCnt,所以这里初始化为n
     99     ans=0;
    100 }
    101 int main () {
    102     int n;
    103     while (scanf("%d %d",&n,&K)!=EOF) {
    104         if (n==0&&K==0) break;
    105         init(n);
    106         for (int i=1;i<n;i++) {
    107             int u,v,w;
    108             scanf("%d %d %d",&u,&v,&w);
    109             addEdge(u,v,w);
    110             addEdge(v,u,w);
    111         }
    112         solve(1);
    113         printf("%d
    ",ans);
    114     }
    115     return 0;
    116 }
  • 相关阅读:
    CSS之APP开发比较实用的CSS属性
    关于 js 中的 call 和 apply使用理解
    灵感一:搜索型APP,帮助读书爱好者,搜索某本书的关键字
    常用排序算法:基数排序
    常用排序算法:桶排序
    常用排序算法:计数排序
    常用排序算法:希尔排序
    常用排序算法:归并排序
    常用排序算法:堆排序
    常用排序算法:快速排序
  • 原文地址:https://www.cnblogs.com/micrari/p/4803021.html
Copyright © 2011-2022 走看看