poj 1741 点分治
来源:互联网 发布:mysql 基数低 不走索引 编辑:程序博客网 时间:2024/05/22 17:51
点分治就是在树上跑分治。
这个题是求树上两两距离小于K的点对有多少.
可以定义length[i]为i点与根结点的距离。
那么对于其不在同一个根儿子子树的点,这样可以全部计算出来了,现在就差每个子树里的点。也就是说,对于这个根,经过其的点的路径全部算出来了。
此时可以把这个根从图中删掉,那么再递归进行处理后面的根,那么得到的结果即可。
每次都寻找重心来进行分治,这样可以使得复杂度为 nlogn
注意写代码的正确性。。
#include <iostream>#include <stdio.h>#include <vector>#include <string.h>#include <algorithm>#include <map>#include<time.h>#include<set>using namespace std;const int maxn=1e4+7;struct ttt{int w,v,next;}edge[maxn+maxn];int head[maxn];int e,n;bool vis[maxn];void init(){ e=0; memset(vis,0,sizeof(vis)); memset(head,-1,sizeof(head));}int K;void add(int u,int v,int w){ e++; edge[e].v=v; edge[e].w=w; edge[e].next=head[u]; head[u]=e;}int mx[maxn],size[maxn],mi,root,dis[maxn],num;//mx用来储存每个结点的最大子树大小,size储存每个结点的子树大小,dis存结点int dfssize(int u,int fa){ //这个函数预处理全部子树的大小和每个点的最大子树大小 int i,v; //cout <<" in in " << u << endl; size[u]=1; //初始大小为1,最大子树大小是0 mx[u]=0; for(i=head[u];i!=-1;i=edge[i].next){ v=edge[i].v; // cout <<"!!!"<<v<< endl; if(v != fa && !vis[v]){ dfssize(v,u); size[u]+=size[v]; mx[u]=max(size[v],mx[u]); } } // cout <<" OUT OUT " << u << endl;}//dfsroot 的fa只用来判不走回去的边,r用来判从进入到这个点的这个方向的点有多少int dfsroot(int r,int u,int fa){ //r是指最开始dfs的那个点 int i,v; if(size[r]-size[u]>mx[u])mx[u]=size[r]-size[u]; //这里是考虑从父节点连接下来的那一边 if(mx[u]<mi)mi=mx[u],root=u;//取最大子树最小的那个点作为根 for(i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(vis[v]==1||v==fa)continue; dfsroot(r,v,u); }}int dfsdis(int u,int d,int fa){ dis[num++]=d; //距离为d int i,v; for(i=head[u];i!=-1;i=edge[i].next){ v=edge[i].v; if(vis[v]==1||v==fa)continue; dfsdis(v,d+edge[i].w,u); }}int calc(int u,int d){//到这个点的距离已经是d了 int ret=0; num=0; dfsdis(u,d,0); //从这个点开始计算出全部点的距离 sort(dis,dis+num); int i=0,j=num-1; while(i<j){ //双指针扫 while(dis[i]+dis[j]>K&&i<j)j--; ret+=j-i;i++; } return ret;}int Sum;int dfs(int u){ // cout <<"in"<< u<< endl; mi=n; dfssize(u,0); dfsroot(u,u,0); Sum+=calc(root,0); //以root作为根去找 vis[root]=1; int i,v; for(i=head[root];i!=-1;i=edge[i].next){ v=edge[i].v; if(!vis[v]){ //每次计算的时候会把同一颗子树上点对也计算了,这样子会重复计算,那么每次剪掉即可 Sum-=calc(v,edge[i].w); dfs(v); } }}int main(){ int i,j,k,f1,f2,f3,f4,t1,t2,t3,t4,m; //freopen("in.txt","r",stdin); while(scanf("%d %d",&n,&m)==2){ if(n+m==0)break; K=m;init(); for(i=1;i<n;i++){ scanf("%d %d %d",&t1,&t2,&t3); add(t1,t2,t3); add(t2,t1,t3); } //for(i=head[1];i!=-1;i=edge[i].next){ // cout << edge[i].v <<endl; //} Sum=0; dfs(1); printf("%d\n",Sum); } return 0;}
阅读全文
0 0
- POJ 1741 点分治
- 【poj 1741】点分治
- POJ-1741 点分治
- POJ 1741 点分治
- poj 1741 点分治
- poj 1741 点分治
- 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 1741Tree(点分治)
- 点分治 POJ 1741 Tree
- POJ-1741 (点分治模板)
- POJ 1741:点分治详解
- 剑指offer 算法2 替换空格(python)
- MySQL表格内容查询基本语句3
- 隐马尔科夫模型(一)
- poj查询区间第k大(划分树)
- linux 中解析命令行参数 (getopt_long用法)
- poj 1741 点分治
- Laravel 同域 不同项目间公用 Cookie 实例
- Ubuntu 中一些包的安装
- UML建模之
- OKHTTP和Retrofit
- libvirt api 虚拟机动态迁移代码示例(非共享存储)
- ORACLE索引原理
- 边框回归(Bounding Box Regression)详解
- js得到连两个时间段之间所有的年-月 获取当前日期 格式化日期 根据指定日期得到该日期该月份的最后一天