zoukankan      html  css  js  c++  java
  • AW252 树(点分治)

    题目地址


    注意点:

    • 枚举阶段时需要用dfs预处理每个点的深度.

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int MAXN=2e4,MAXM=3e4;
    struct Edge{
    	int from,to,w,nxt;
    }e[MAXM];
    int head[MAXN],edgeCnt=1;
    void addEdge(int u,int v,int w){
    	e[++edgeCnt].from=u;
    	e[edgeCnt].to=v;
    	e[edgeCnt].w=w;
    	e[edgeCnt].nxt=head[u];
    	head[u]=edgeCnt;
    }
    bool vis[MAXN],w[MAXN];
    int siz[MAXN];
    int pos,ans;
    void dfs_find(int restSiz,int x){
    	vis[x]=1;
    	siz[x]=1;
    	int maxSiz=0;
    	for(int i=head[x];i;i=e[i].nxt){
    		int nowV=e[i].to;
    		if(vis[nowV]||w[nowV])continue;
    		dfs_find(restSiz,nowV);
    		siz[x]+=siz[nowV];
    		maxSiz=max(maxSiz,siz[nowV]);
    	}
    	maxSiz=max(maxSiz,restSiz-siz[x]);
    	if(maxSiz<ans)ans=maxSiz,pos=x;
    }
    int dep[MAXN],tot,cnt[MAXN];
    int a[MAXN],b[MAXN];
    void dfs(int x){
    	vis[x]=1;
    	for(int i=head[x];i;i=e[i].nxt){
    		int nowV=e[i].to,nowW=e[i].w;
    		if(vis[nowV]||w[nowV])continue;
    		a[++tot]=nowV,b[nowV]=b[x];
    		cnt[b[x]]++;
    		dep[nowV]=dep[x]+nowW;//
    		dfs(nowV);
    	}
    }
    bool cmp(int x,int y){
    	return dep[x]<dep[y];
    }
    int Ans;
    void reset(){
    	memset(dep,0,sizeof(dep));
    	memset(cnt,0,sizeof(cnt));
    	memset(vis,0,sizeof(vis));
    	tot=1;
    }
    int k;
    void work(int restSiz,int x){
    	memset(vis,0,sizeof(vis));
    	ans=restSiz;
    	dfs_find(restSiz,x);
    	reset();
    	a[tot]=b[pos]=pos;
    	w[pos]=1,cnt[pos]++;
    	for(int i=head[pos];i;i=e[i].nxt){
    		int nowV=e[i].to,nowW=e[i].w;
    		if(vis[nowV]||w[nowV])continue;
    		a[++tot]=b[nowV]=nowV;
    		cnt[nowV]++,dep[nowV]=nowW;
    		dfs(nowV);
    	}
    	sort(a+1,a+1+tot,cmp);
    	int l=1,r=tot;
    	cnt[b[a[1]]]--;
    	while(l<r){
    		while(dep[a[l]]+dep[a[r]]>k)cnt[b[a[r--]]]--;
    		Ans+=r-l-cnt[b[a[l]]];
    		cnt[b[a[++l]]]--;
    	}
    	int nowU=pos;
    	for(int i=head[nowU];i;i=e[i].nxt){
    		int nowV=e[i].to;
    		if(w[nowV])continue;
    		work(siz[nowV],nowV);
    	}
    }
    void init(){
    	memset(head,0,sizeof(head));
    	edgeCnt=1;
    }
    int main(){
    	int n;
    	while(1){
    		scanf("%d%d",&n,&k);
    		if(!n)break;
    		init();
    		for(int i=1;i<=n-1;i++){
    			int u,v,cost;
    			scanf("%d%d%d",&u,&v,&cost);
    			addEdge(u,v,cost);
    			addEdge(v,u,cost);
    		}
    		memset(w,0,sizeof(w));
    		Ans=0;
    		work(n,1);
    		printf("%d
    ",Ans);
    	}
    	return 0;
    }
  • 相关阅读:
    QT中PRO文件写法的详细介绍,很有用,很重要!
    What is the difference between authorized_key and known_host file for SSH
    SHELL DATE 命令详解
    Sample program to use PC/SC API.
    如何让用户关闭客户端IE时,触发Session_End事件
    Sql Create Function简单例子
    Css2.0实现圆角边框
    运算符重载的一个例子
    HTML获取URL传递的参数
    C#中自定义属性的例子
  • 原文地址:https://www.cnblogs.com/zbsy-wwx/p/11680540.html
Copyright © 2011-2022 走看看