poj 1741 Tree (点的分治)
来源:互联网 发布:手机数据分析软件 编辑:程序博客网 时间:2024/05/21 08:40
题意:给你一棵树,问在树上有多少点对之间的最短距离小于等于K,且(a,b)和(b,a)算一个
思路:这题可以用点的分治来做,选取点为这棵树的重心,即最大子树最小的点。然后可以分两种情况进行处理,过这一点与不过这一点,而不过这一点就递归处理它的子树即可。
在统计的时候要注意,先算出到根节点的距离,然后排序,存入一个队列当中,统计时则可以根据头尾两个数相加来决定中间数的大小,因而 可以进行快速的统计。但是要注意减去一些情况,比如2结点到3结点经过1结点的距离计算时都要经过1到其儿子结点的一条边。这不是最短的要排除。
这里计算重心时我只是用了一个DFS,感觉应该可以快些。
代码如下:
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#define inf 10000000using namespace std;const int maxn=11111;struct node{ int to; int next; int w;};node edge[maxn<<2];int head[maxn];int dp[maxn];int vis[maxn];int wei_cen;int dist[maxn];int tot;int minn;int ans;int e_sz;int n;int k;void init(){ memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); e_sz=0; ans=0;}void addedge(int a,int b,int c)//加边{ edge[e_sz].to=b; edge[e_sz].w=c; edge[e_sz].next=head[a]; head[a]=e_sz++;}int dfs_cal(int u,int fa,int size)//计算重心{ dp[u]=1; int maxx=0; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v!=fa&&(!vis[v])) { dfs_cal(v,u,size); dp[u]+=dp[v]; maxx=max(maxx,dp[v]); } } maxx=max(maxx,size-dp[u]); if(minn>maxx) { minn=maxx; wei_cen=u; } return wei_cen;}void getdis(int u,int fa,int dis)//求距离{ dist[tot++]=dis; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if((v!=fa)&&(!vis[v])&&(dis+edge[i].w<=k)) { getdis(v,u,dis+edge[i].w); } }}void count1(int s)//计算点对数目{ sort(dist,dist+tot); int left=0,right=tot-1; while(left<right) { if(dist[left]+dist[right]<=k) { ans+=right-left; left++; } else { right--; } }}void count2(int s)// 除去不可行的{ vis[s]=1; for(int i=head[s];i!=-1;i=edge[i].next) { int v=edge[i].to; if(!vis[v]) { tot=0; getdis(v,s,edge[i].w); sort(dist,dist+tot); int left=0; int right=tot-1; while(left<right) { if(dist[left]+dist[right]<=k) { ans-=right-left; left++; } else { right--; } } } }}void dfs(int s,int fa,int size)//递归求解{ minn=inf; int root=dfs_cal(s,fa,size); tot=0; // cout<<root<<endl; getdis(root,0,0); count1(root); count2(root); // cout<<ans<<endl; for(int i=head[root];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v!=fa&&(!vis[v])) { // cout<<s<<" "<<v<<endl; dfs(v,root,dp[v]); } }}int main(){ // freopen("in.txt","r",stdin); while(scanf("%d%d",&n,&k),n||k) { init(); for(int i=0;i<n-1;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); addedge(a,b,c); addedge(b,a,c); } dfs(1,0,n); printf("%d\n",ans); } return 0;}
- 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, 树的重心, 树分治, 点分治
- poj 1741 Tree 点分治
- 【POJ 1741】 Tree --点分治
- 【POJ】1741 Tree 点分治
- 【POJ】1741 Tree 点分治
- poj 1741 Tree 点分治
- POJ 1741 Tree 点分治
- poj 1741 Tree 点分治
- POJ 1741 Tree 点分治
- 逆向编程培训(第三课)
- (转)更改MyEclipse中的src目录的浏览方式
- 何时对你说再见--深圳。
- Linux时间戳、时间类型转换
- The declared package "" does not match the expected package
- poj 1741 Tree (点的分治)
- system.web.extensions TYPE错误
- AJAX笔记
- 写给刚刚使用DXP的人
- Mahout推荐算法基础
- Win32多线程之线程上下文切换(Context Switching)
- windows7 Run命令运行程序列表
- 无法打开模块文件“C:\Users\sq\AppData\Local\Temp\.NETFramework,Version=v4.5,AssemblyAttributes.vb”:系统找不到指定的文件
- 片上总线Wishbone 学习(六)总线周期之操作发起