zoukankan      html  css  js  c++  java
  • POJ1741 Tree

    前言

    今天刚刚学了点分治,赶紧把思路写一下,以防止以后忘记

    分析

    对于一个点,经过它的路径有两种可能,一是在一棵子树里(下图1-2-4),二是在两个子树里(下图2-1-5)。

    那么对于情况二,我们可以把它拆成两条链相加。
    对于情况一好像不行,但如果去分类讨论就会让程序更加复杂,但是发现它在它的子树里处理这种情况时就成了情况二,所以可以暂时不用管它,在递归下一层的时候返回来处理就行,不过需要加一个vis数组,防止情况搜多,这样就能够处理这种情况了。
    但是有一种路径需要被减去,即合并(1-2-3和1-2-4)这种路径,因为显然不能合并啊,所以要减去。
    减的方法是在往下递归的时候,以连向父节点的那条边的权值为起始值处理一遍答案,这种就相当于,模拟了一下从1搜下来的时候的情况,但是只搜这一棵树,就能够求出曾经多算的情况。
    还有为了防止不会搜太多层,需要从重心开始搜。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int lqs=1e4+10;
    struct Edge{
    	int to,nxt,val;
    }e[lqs<<1];
    int h[lqs],idx;
    void Ins(int a,int b,int c){
    	e[++idx].to=b;e[idx].val=c;
    	e[idx].nxt=h[a];h[a]=idx;
    }
    int n,k,rt,T,siz[lqs],w[lqs];
    bool vis[lqs];
    void dfs1(int u,int fa){
    	siz[u]=1;w[u]=0;
    	for(int i=h[u];i;i=e[i].nxt){
    		int v=e[i].to;
    		if(vis[v]||v==fa)continue;
    		dfs1(v,u);
    		siz[u]+=siz[v];
    		w[u]=max(w[u],siz[v]);
    	}
    	w[u]=max(w[u],T-siz[u]);
    	if(w[u]<w[rt])rt=u;
    }
    int a[lqs],hh;
    void dfs2(int u,int fa,int d){
    	a[++hh]=d;
    	for(int i=h[u];i;i=e[i].nxt){
    		int v=e[i].to;
    		if(vis[v]||v==fa)continue;
    		dfs2(v,u,d+e[i].val);
    	}
    }
    int ans;
    int calc(int u,int d){
    	hh=0;
    	int sum=0;
    	dfs2(u,0,d);
    	sort(a+1,a+hh+1);
    	for(int i=1,j=hh;;i++){
    		while(j&&a[i]+a[j]>k)j--;
    		if(i>j)break;
    		sum+=j-i+1;
    	}
    	return sum;
    }
    void solve(int u){
    	ans+=calc(u,0);
    	vis[u]=1;
    	for(int i=h[u];i;i=e[i].nxt){
    		int v=e[i].to;
    		if(vis[v])continue;
    		ans-=calc(v,e[i].val);
    		T=siz[v];rt=0;
    		dfs1(v,0);
    		solve(rt);
    	}
    }
    void init(){
    	memset(h,0,sizeof(h));
    	ans=rt=idx=0;
    	memset(vis,0,sizeof(vis));
    }
    int main(){
    	w[0]=0x7f7f7f7f;
    	while(~scanf("%d%d",&n,&k)&&n&&k){
    		init();
    		for(int i=1;i<n;i++){
    			int a,b,c;
    			scanf("%d%d%d",&a,&b,&c);
    			Ins(a,b,c);Ins(b,a,c);
    		}
    		T=n;
    		dfs1(1,0);
    		solve(rt);
    		printf("%d
    ",ans-n);
    	}
    }
    
  • 相关阅读:
    css的一些记录——“Unexpected missing generic font family”
    idea右键java文件找到对应的class文件路径以及查看class文件
    redis的一些记录
    【转】解决IDEA2020控制台乱码的方法
    【转】java去除html代码中含有的html、js、css标签,获取文字内容
    linux 中 AGE的含义
    控制反转容器比较:TinyIoC vs Autofac
    C# 异步方法,尽量避免使用async void而是要用async Task
    xamarin 实现选择文件功能
    xamarin手写签名
  • 原文地址:https://www.cnblogs.com/anyixing-fly/p/12992052.html
Copyright © 2011-2022 走看看