POJ 1741 Tree(树+点分治)
2016-02-26 23:59
447 查看
题意:
题意就不说了,学树分治的入门题。要学树分治的话,首先把漆子超的论文看一遍:戳这里
然后去找几个博客看看也就能大概理解意思了,但是实现还是有点困难的,所以我不去讲树分治的思想了,讲也讲不好,我就讲讲具体过程吧,以方便自己写,而不用抄别人的模板。
1、我们找到以当前节点为根的子树的重心。
2、将重心删除,对重心的每一个子节点递归解决问题。
3、对重心的每一个根节点,统计距离,并且计算答案,统计答案的方法我也不多说了,贴一发题解:戳这里
4、恢复重心。
其中,寻找重心是一个树形dp,比较好理解。
代码:
题意就不说了,学树分治的入门题。要学树分治的话,首先把漆子超的论文看一遍:戳这里
然后去找几个博客看看也就能大概理解意思了,但是实现还是有点困难的,所以我不去讲树分治的思想了,讲也讲不好,我就讲讲具体过程吧,以方便自己写,而不用抄别人的模板。
1、我们找到以当前节点为根的子树的重心。
2、将重心删除,对重心的每一个子节点递归解决问题。
3、对重心的每一个根节点,统计距离,并且计算答案,统计答案的方法我也不多说了,贴一发题解:戳这里
4、恢复重心。
其中,寻找重心是一个树形dp,比较好理解。
代码:
// // Created by CQU_CST_WuErli // Copyright (c) 2016 CQU_CST_WuErli. All rights reserved. // #include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> #include <cctype> #include <cmath> #include <string> #include <vector> #include <list> #include <map> #include <queue> #include <stack> #include <set> #include <algorithm> #include <sstream> #define CLR(x) memset(x,0,sizeof(x)) #define OFF(x) memset(x,-1,sizeof(x)) #define MEM(x,a) memset((x),(a),sizeof(x)) #define BUG cout << "I am here" << endl #define lookln(x) cout << #x << "=" << x << endl #define SI(a) scanf("%d",&a) #define SII(a,b) scanf("%d%d",&a,&b) #define SIII(a,b,c) scanf("%d%d%d",&a,&b,&c) #define rep(flag,start,end) for(int flag=start;flag<=end;flag++) #define Rep(flag,start,end) for(int flag=start;flag>=end;flag--) #define Lson l,mid,rt<<1 #define Rson mid+1,r,rt<<1|1 #define Root 1,n,1 #define BigInteger bign const int MAX_L=2005;// For BigInteger const int INF_INT=0x3f3f3f3f; const long long INF_LL=0x7fffffff; const int MOD=1e9+7; const double eps=1e-9; const double pi=acos(-1); typedef long long ll; using namespace std; const int N=1e4+100; int n,k; int pnt[N<<1],nxt[N<<1],head ,w[N<<1]; int cnt; void add_edge(int u,int v,int cost) { pnt[cnt]=v;nxt[cnt]=head[u];w[cnt]=cost;head[u]=cnt++; } int centroid; int sz ,mx ; int vis ; int ans; int getSize(int fa,int u) { int ret=1; for (int i=head[u];~i;i=nxt[i]) { int v=pnt[i]; if (vis[v] || v==fa) continue; ret+=getSize(u,v); } return ret; } void getCentroid(int fa,int u,int all) { sz[u]=1;mx[u]=0; for (int i=head[u];~i;i=nxt[i]) { int v=pnt[i]; if (v==fa || vis[v]) continue; getCentroid(u,v,all); sz[u]+=sz[v]; mx[u]=max(mx[u],sz[v]); } mx[u]=max(mx[u],all-sz[u]); if (!centroid || mx[u]<mx[centroid]) centroid=u; } void getDis(int fa,int u,int dis,vector<int>& ds) { ds.push_back(dis); for (int i=head[u];~i;i=nxt[i]) { int v=pnt[i]; if (vis[v] || v==fa) continue; getDis(u,v,dis+w[i],ds); } } int cal(vector<int>& ds) { sort(ds.begin(),ds.end()); int ret=0; for (int i=0,j=ds.size()-1;i<j;i++) { while (i<j && ds[i]+ds[j]>k) j--; ret+=j-i; } return ret; } void solve(int u) { // lookln(u); centroid=0; getCentroid(-1,u,getSize(-1,u)); int x=centroid; vis[x]=1; for (int i=head[x];~i;i=nxt[i]) { int v=pnt[i]; if (vis[v]) continue; solve(v); } vector<int> ds; ds.push_back(0); for (int i=head[x];~i;i=nxt[i]) { int v=pnt[i]; if (vis[v]) continue; vector<int> tds; getDis(x,v,w[i],tds); ans-=cal(tds); ds.insert(ds.end(),tds.begin(),tds.end()); } ans+=cal(ds); vis[x]=0; } int main(int argc, char const *argv[]) { #ifdef LOCAL freopen("C:\\Users\\john\\Desktop\\in.txt","r",stdin); // freopen("C:\\Users\\john\\Desktop\\out.txt","w",stdout); #endif while(SII(n,k)==2 && (n|| k)) { OFF(head);cnt=0; rep(i,1,n-1) { int u,v,cost; SIII(u,v,cost); // cout << u << ' ' << v << ' ' << cost << endl; add_edge(u,v,cost); add_edge(v,u,cost); } ans=0; solve(1); cout << ans << endl; } return 0; }
相关文章推荐
- C++ 造房子list
- hdu1016-Prime Ring Problem(简单dfs)
- [ahk]选中内容 按热键即发音
- 使用UDP的connect获取本机IP
- 蓝桥杯G将军
- CCF 201509-4 高速公路
- C 语言算法排序 希尔
- Android Fragment
- mac下配置jsp开发环境——tomcat安装及配置
- Android--Dialog对话框
- thinkphp使用js实现点击加载更多后, 底部无刷新加载出新的数据并显示在该页
- 【学习笔记】day1_快速入门 03_Android体系结构
- Leetcode ☞ 238. Product of Array Except Self ☆
- 外键的使用
- CoInitializeEx 与CoInitialize的区别
- 在Ubuntu上安装使用Systemtap
- 328. Odd Even Linked List
- DirectX SDK 与 DirectShow SDK
- 2016/2/26 jQuery的技术 1,安装 2,语法选择器$ 事件触发 3,常用jQuery函数
- ssh2-hibernate错误小结