zoukankan      html  css  js  c++  java
  • POJ 1741 点分治

    方法:指针扫描数组

    每次选择树的重心作为树根,从树根出发进行一次DFS,求出点到树根的距离,把节点按照与树根的的距离放进数组d,设置两个指针L,R分别从前、后开始扫描,每次满足条件时答案累加R-L。,之后减去子树的满足条件的情况,删除根节点,对其子树继续上述操作,不断累加答案。

    代码:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int maxn=100010;
    vector<pair<int,int> >G[maxn];
    int d[maxn],size[maxn],root,max_w,n1,cnt,n,k;
    bool vis[maxn];
    void get_root(int x,int f){//求树的重心 
    	size[x]=1;
    	int max_part=0;
    	for(int i=0;i<G[x].size();i++){
    		int Next=G[x][i].first;
    		if(Next!=f&&!vis[Next]){
    			get_root(Next,x);
    			size[x]+=size[Next];
    			max_part=max(max_part,size[Next]);
    		}
    	}
    	max_part=max(max_part,n1-size[x]);
    	if(max_part<max_w){
    		root=x;
    		max_w=max_part;
    	}
    }
    void get_dist(int x,int f,int dist){//算距离 
    	d[++cnt]=dist;
    	size[x]=1;//算距离的同时也更新一下子树的大小 
    	for(int i=0;i<G[x].size();i++){
    		int Next=G[x][i].first;
    		if(Next!=f&&!vis[Next]){
    			get_dist(Next,x,dist+G[x][i].second);
    			size[x]+=size[Next];
    		}
    	}
    }
    int cal(int x,int y){//计算 
    	cnt=0;
    	get_dist(x,-1,y);
    	sort(d+1,d+1+cnt);
    	int ans=0;
    	for(int i=1,j=cnt;i<j;i++){
    		while(d[i]+d[j]>k&&i<j)j--;
    		ans+=j-i;
    	}
    	return ans;
    }
    int dfs(int x){//dfs主框架 
    	max_w=n1;
    	get_root(x,-1);
    	int now=root;
    	vis[now]=1;
    	int ans=0;
    	ans+=cal(now,0);
    	for(int i=0;i<G[now].size();i++){
    		int Next=G[now][i].first;
    		if(!vis[Next]){
    			ans-=cal(Next,G[now][i].second);
    			n1=size[Next];
    			ans+=dfs(Next);
    		}
    	}
    	return ans;
    }
    void init(int n){
    	for(int i=1;i<=n;i++)G[i].clear();
    	cnt=0;
    	memset(vis,0,sizeof(vis));
    }
    int main(){
    	int u,v,dis;
    	while(~scanf("%d%d",&n,&k)&&n&&k){
    		init(n);
    		for(int i=1;i<n;i++){
    			scanf("%d%d%d",&u,&v,&dis);
    			G[u].push_back(make_pair(v,dis));
    			G[v].push_back(make_pair(u,dis));
    		}
    		n1=n;
    		printf("%d
    ",dfs(1));
    	}
    }
    //5 1
    //1 2 1
    //2 3 1
    //3 4 1
    //4 5 1
  • 相关阅读:
    一天一道算法题---6.8--数学题
    TOJ----1037---最大独立集
    一天一道算法题---6.6---排列递推(我不会)
    一天一道算法题---6.4--中途相遇法
    一天一道算法题--6.5--数学题
    夜太美---酒不醉--人自醉
    SSH组合之Spring3整合Hibernate4(一)
    Hibernater入门
    Java微信公众平台进入开发模式
    新浪sae平台进行数据库的连接
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/9709941.html
Copyright © 2011-2022 走看看