树分治算法
来源:互联网 发布:kings and queens知乎 编辑:程序博客网 时间:2024/06/06 19:37
树分治
树分治有两种:
分治策略:
POJ 1741
#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>#include <time.h>using namespace std;const int MAXN = 10010;const int INF = 0x3f3f3f3f;struct Edge{ int to,next,w;}edge[MAXN*2];int head[MAXN],tot;void init(){ tot = 0; memset(head,-1,sizeof(head));}void addedge(int u,int v,int w){ edge[tot].to = v; edge[tot].w = w; edge[tot].next = head[u];head[u] = tot++;}bool vis[MAXN];int size[MAXN],dep[MAXN];int le,ri;int dfssize(int u,int pre){ size[u] = 1; for(int i = head[u];i != -1;i = edge[i].next) { int v = edge[i].to; if(v == pre || vis[v])continue; size[u] += dfssize(v,u); } return size[u];}int minn;//找重心void getroot(int u,int pre,int totnum,int &root){ int maxx = totnum - size[u]; for(int i = head[u];i != -1;i = edge[i].next) { int v = edge[i].to; if(v == pre || vis[v])continue; getroot(v,u,totnum,root); maxx = max(maxx,size[v]); } if(maxx < minn){minn = maxx; root = u;}}void dfsdepth(int u,int pre,int d){ dep[ri++] = d; for(int i = head[u];i != -1;i = edge[i].next) { int v = edge[i].to; if(v == pre || vis[v])continue; dfsdepth(v,u,d+edge[i].w); }}int k;int getdep(int a,int b){ sort(dep+a,dep+b); int ret = 0, e = b-1; for(int i = a;i < b;i++) { if(dep[i] > k)break; while(e >= a && dep[e] + dep[i] > k)e--; ret += e - a + 1; if(e > i)ret--; } return ret>>1;}int solve(int u){ int totnum = dfssize(u,-1); int ret = 0; minn = INF; int root; getroot(u,-1,totnum,root); vis[root] = true; for(int i = head[root];i != -1;i = edge[i].next) { int v = edge[i].to; if(vis[v])continue; ret += solve(v); } le = ri = 0; for(int i = head[root];i != -1;i = edge[i].next) { int v = edge[i].to; if(vis[v])continue; dfsdepth(v,root,edge[i].w); ret -= getdep(le,ri); le = ri; } ret += getdep(0,ri); for(int i = 0;i < ri;i++) { if(dep[i] <= k)ret++; else break; } vis[root] = false; return ret;}int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int n; int u,v,w; while(scanf("%d%d",&n,&k) == 2) { if(n == 0 && k == 0)break; init(); for(int i = 1;i < n;i++) { scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } memset(vis,false,sizeof(vis)); printf("%d\n",solve(1)); } return 0;}
阅读全文
0 0
- 树分治算法
- 分治算法
- 分治算法
- 分治算法?
- 【算法】分治
- 【算法】分治
- 分治算法
- 分治算法
- 分治算法
- 分治算法
- 分治算法
- 分治算法
- 分治算法
- 分治算法
- 分治算法
- 分治算法
- 分治算法
- 分治算法
- CSS3 经典教程系列:CSS3 线性渐变(linear-gradient)
- 微信基础开发
- redis的安装(Linux与Windows)
- 2017秋季慕课尔雅中国文明史上答案章节测验答案
- 拉格朗日乘子法的由来
- 树分治算法
- c的数据类型
- C 运算符与表达式
- Linux 开机引导和启动过程详解
- Wheel Joint 2D 属性面板简介
- Win10安装msi程序报错2503和2502错误解决方案
- week_1_Two Sum
- 《Java源码分析》:Stack
- Leetcode 258 Add Digits