点分治学习记录

学习了一下点分治

POJ 1741(由于poj不支持c++11和bits,改一下即可ac)

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define ll long long
  4 struct edge
  5 {
  6     int to,val;
  7     edge(int a,int b)
  8     {to=a,val=b;}
  9 };
 10 const int maxn=10005;
 11 vector<edge>G[maxn];
 12 int sz[maxn],f[maxn],used[maxn],rt;
 13 int n,size,k;
 14 ll ans;
 15 void getrt(int u,int fa)
 16 {
 17     f[u]=0;
 18     sz[u]=1;
 19     for(auto i:G[u])
 20     {
 21         int v=i.to;
 22         if(v==fa || used[v]) continue;
 23         getrt(v,u);
 24         sz[u]+=sz[v];
 25         f[u]=max(f[u],sz[v]);
 26     }
 27     f[u]=max(f[u],size-sz[u]);
 28     if(f[u]<f[rt]) rt=u;
 29 }
 30 int d[maxn];
 31 vector<int>tmp;
 32 void dfs(int u,int fa)
 33 {
 34     for(auto i:G[u])
 35     {
 36         int v=i.to,val=i.val;
 37         if(v==fa || used[v]) continue;
 38         d[v]=d[u]+val;
 39         tmp.push_back(d[v]);
 40         dfs(v,u);
 41     }
 42 }
 43 int calc(int u,int dep)
 44 {
 45     tmp.clear();
 46     d[u]=dep;
 47     tmp.push_back(d[u]);
 48     dfs(u,0);
 49     sort(tmp.begin(),tmp.end());
 50     int ret=0;
 51     for(int l=0,r=tmp.size()-1;l<tmp.size() && l<r;l++)
 52     {
 53         if(2*tmp[l]>k) break;
 54         while(tmp[l]+tmp[r]>k) r--;
 55         if(l>=r) break;
 56         ret+=r-l;
 57     }
 58     return ret;
 59 }
 60 void divide(int now)
 61 {
 62     ans+=calc(now,0);
 63     used[now]=1;
 64     for(auto i:G[now])
 65     {
 66         int v=i.to,val=i.val;
 67         if(used[v]) continue;
 68         ans-=calc(v,val);
 69         rt=0;
 70         size=sz[v];
 71         getrt(v,0);
 72         divide(rt);
 73     }
 74 }
 75 void init()
 76 {
 77     f[0]=1e9+7;
 78     for(int i=1;i<=n;i++) used[i]=0,G[i].clear();
 79     rt=ans=0;
 80 }
 81 int main()
 82 {
 83     #ifdef amori
 84     freopen("in.txt","r",stdin);
 85     #endif // amori
 86     while(~scanf("%d%d",&n,&k))
 87     {
 88         if(!n && !k) break;
 89         init();
 90         for(int i=1;i<n;i++)
 91         {
 92             int u,v,w;
 93             scanf("%d%d%d",&u,&v,&w);
 94             G[u].push_back(edge(v,w));
 95             G[v].push_back(edge(u,w));
 96         }
 97         getrt(1,0);
 98         divide(rt);
 99         printf("%d\n",ans);
100     }
101 }
View Code

注意事项:初始化时设f[0]为inf,每次重新获取重心(getrt)的时候,将rt初始化为0,size初始化为子树的大小(sz[v])。

猜你喜欢

转载自www.cnblogs.com/iamamori/p/10858326.html