zoukankan      html  css  js  c++  java
  • POJ 1987 BZOJ 3365 Distance Statistics 树的分治(点分治)

    题目大意:(同poj1741,刷一赠一系列)


    CODE:


    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define MAX 40010
    #define INF 0x3f3f3f3f
    using namespace std;
    
    int points,edges,k;
    int head[MAX],total;
    int next[MAX << 1],length[MAX << 1],aim[MAX << 1];
    
    bool v[MAX];
    int cnt[MAX];
    int _size,size[MAX],root,_total;
    int dis[MAX],p;
    
    char s[10];
    
    inline void Add(int x,int y,int len);
    
    void Work(int x);
    void GetRoot(int x,int last);
    inline int Count(int x,int len);
    void GetDis(int x,int last,int len);
    
    int main()
    {
    	cin >> points >> edges;
    	for(int x,y,z,i = 1;i <= edges; ++i) {
    		scanf("%d%d%d%s",&x,&y,&z,s);
    		Add(x,y,z),Add(y,x,z);
    	}
    	cin >> k;
    	Work(1);
    	int ans = 0;
    	for(int i = 1;i <= points; ++i)
    		ans += cnt[i];
    	cout << ans << endl;
    	return 0;
    }
    
    inline void Add(int x,int y,int len)
    {
    	next[++total] = head[x];
    	aim[total] = y;
    	length[total] = len;
    	head[x] = total;
    }
    
    void Work(int x)
    {
    	_total = size[x] ? size[x]:points;
    	_size = INF;
    	GetRoot(x,0);
    	x = root;
    	v[x] = true;
    	cnt[x] = Count(x,0);
    	for(int i = head[x];i;i = next[i]) {
    		if(v[aim[i]])	continue;
    		cnt[x] -= Count(aim[i],length[i]);
    		Work(aim[i]);
    	}
    }
    
    void GetRoot(int x,int last)
    {
    	size[x] = 1;
    	int max_size = 0;
    	for(int i = head[x];i;i = next[i]) {
    		if(v[aim[i]] || aim[i] == last)	continue;
    		GetRoot(aim[i],x);
    		size[x] += size[aim[i]];
    		max_size = max(max_size,size[aim[i]]);
    	} 
    	max_size = max(max_size,_total - size[x]);
    	if(_size > max_size)
    		_size = max_size,root = x;
    }
    
    inline int Count(int x,int len)
    {
    	p = 0;
    	GetDis(x,0,len);
    	sort(dis + 1,dis + p + 1);
    	int l = 1,r = p,re = 0;
    	while(l < r) {
    		if(dis[l] + dis[r] <= k)
    			re += (r - l),++l;
    		else	--r;
    	}
    	return re;
    }
    
    void GetDis(int x,int last,int len)
    {
    	dis[++p] = len;
    	for(int i = head[x];i;i = next[i]) {
    		if(v[aim[i]] || aim[i] == last)	continue;
    		GetDis(aim[i],x,len + length[i]);
    	}
    }


  • 相关阅读:
    7月18日实习日志
    第二周总结
    7月15日实习日志
    7月14日实习日志
    7月13日实习日志
    7月12日实习日志
    7月11日实习日志
    第一周总结
    7月8日实习日志
    小飞机工作笔记(一)方案简述
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4025761.html
Copyright © 2011-2022 走看看