poj 1741 Tree 树的分治
来源:互联网 发布:淘宝怎么申请换货 编辑:程序博客网 时间:2024/06/05 17:18
这个题自己完全不会做,,,只是看了解题报告之后自己尝试写了一遍。发现思路很是清晰
首先是涉及到了树怎样进行分治,然后就引入了重心的概念,所谓树的重心就是删除这个点之后所得到的所有子树的最大顶点数最小,这样的话不管怎么切割这颗树,复杂度都不会退化得太严重
然后具体算法就是把这颗树以重心为顶点分为几颗子树,那么满足条件的点对,要么是在同一子树中,要么是在不同两颗子树中,要么其中一个点是重心,就这样递归处理这颗树就能得到答案了,不过在统计的时候有可能出现重复统计的时候,应当删除掉。
#include<iostream>#include<sstream>#include<cstdio>#include<cstring>#include<cmath>#include<queue>#include<stack>#include<math.h>#include<map>#include<time.h>#include<set>#include<string>#include<vector>#include<algorithm>using namespace std;#define inf 0x7fffffff#define lc l,m,index<<1#define rc m+1,r,index<<1|1#define max_n 200005#define mod 10000007#define LL long longint n,k;struct edge{ int to,length;};int ans;vector<edge>G[max_n];int num[max_n]; //统计子树节点个数bool use[max_n]; //记录节点是否被当做重心void init(){ for(int i=0;i<=10005;i++) G[i].clear(); memset(num,0,sizeof(num)); memset(use,false,sizeof(use));}int cntnum(int v,int p) //返回子树节点个数{ int c=1; for(int i=0;i<G[v].size();i++) { int w=G[v][i].to; if(w!=p && !use[w]) { c+=cntnum(w,v); } } num[v]=c; return c;}pair<int ,int > findcen(int v,int p,int t) //寻找重心,返回值为最大顶点数和顶点编号{ int s=1,m=0; pair<int,int> res = make_pair(inf,-1); for(int i=0;i<G[v].size();i++) { int w=G[v][i].to; if(w==p || use[w])continue; res=min(res,findcen(w,v,t)); s+=num[w]; m=max(m,num[w]); } m=max(t-s,m); res=min(res,make_pair(m,v)); return res;}void findlen(int v,int p,int d,vector<int> &ds) //记录其他点距离中心点的距离{ ds.push_back(d); for(int i=0;i<G[v].size();i++) { int w=G[v][i].to; if(w==p || use[w])continue; findlen(w,v,d+G[v][i].length,ds); }}int judge(vector<int> &ds){ int res=0; sort(ds.begin(),ds.end()); int j=ds.size(); for(int i=0;i<ds.size();i++) { while(j>0 && ds[i]+ds[j-1]>k)j--; res+=j-(j>i?1:0); } // printf(" res === %d\n",res); return res/2;}void solve_problem(int v) //solve{ cntnum(v,-1); int s=findcen(v,-1,num[v]).second; use[s]=true; //1 for(int i=0;i<G[s].size();i++) { if(use[G[s][i].to]) continue; solve_problem(G[s][i].to); } //2,3; vector<int> d; d.push_back(0); for(int i=0;i<G[s].size();i++) { int w=G[s][i].to; if(use[w])continue; vector<int>ds; findlen(w,s,G[s][i].length,ds); ans-=judge(ds); // printf("ans == %d \n",ans); d.insert(d.end(),ds.begin(),ds.end()); } ans+=judge(d); // printf("ans == %d\n",ans); use[s]=false;}void solve(){ ans=0; solve_problem(1); printf("%d\n",ans);}int main(){ while(~scanf("%d%d",&n,&k) && !(n==0 && k==0)) { init(); for(int i=0;i<n-1;i++) { int a,b,l; scanf("%d%d%d",&a,&b,&l); edge e; e.length=l; e.to=b; G[a].push_back(e); e.to=a; G[b].push_back(e); } solve(); } return 0;}
0 0
- POJ 1741 Tree 树的分治
- poj 1741 Tree 树的分治
- poj 1741 Tree(树的分治)
- POJ 1741 Tree 树的点分治
- poj 1741 Tree 树的分治
- poj 1741 Tree 树的分治
- POJ - 1741 Tree 树的分治
- POJ 1741Tree 树的分治
- [POJ 1741] Tree (树的分治)
- poj 1741 Tree(树的分治)
- Poj-1741 Tree(树的点分治)
- 【poj 1741】tree 树的点分治
- poj 1741 Tree (树的分治)
- POJ 1741 Tree 树的点分治
- poj 1741 Tree 树的点分治
- POJ 1741 Tree 树的点分治
- POJ 1741 Tree, 树的重心, 树分治, 点分治
- POJ 1741 Tree 树的分治(点分治)
- Linux入门——适合初学者
- 基于lucene的案例开发:查询语句创建PackQuery
- Unity3D–Texture图片空间和内存占用分析
- Bctf Zhongguancun分析
- KAFKA删除topic
- poj 1741 Tree 树的分治
- kernel panic - not syncing:Attempted to kill init
- zend-framwork 框架下的数据库认证(用户登录认证)
- 大神 PK 红米背后,2G 内存将成互联网手机分水岭
- Java数据结构---链表常用操作(I)
- poj 3281 Dining (最大流)
- 华为模拟题一:密码截取C++实现
- 通过socket读取异地文件
- Python编程基础之十五网络编程