• ●POJ 1741 Tree


    题链:

    http://poj.org/problem?id=1741
    题解:

    树上点分治。
    入门题,不多说了。


    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #define MAXN 10004
    using namespace std;
    struct EDGE{
    	int ent;
    	int to[MAXN*2],nxt[MAXN*2],val[MAXN*2],head[MAXN];
    	void Reset(){ent=2; memset(head,0,sizeof(head));}
    	void Adde(int u,int v,int w){
    		to[ent]=v; val[ent]=w; nxt[ent]=head[u]; head[u]=ent++;
    		to[ent]=u; val[ent]=w; nxt[ent]=head[v]; head[v]=ent++;
    	}
    }E;
    int N,K;
    long long ANS;
    int size[MAXN];
    bool vis[MAXN];
    void getroot(int u,int dad,int num,int &root,int &rootnum){
    	int maxnum=0; size[u]=0;
    	for(int i=E.head[u];i;i=E.nxt[i]){
    		if(E.to[i]==dad||vis[E.to[i]]) continue;
    		getroot(E.to[i],u,num,root,rootnum);
    		size[u]+=size[E.to[i]];
    		maxnum=max(maxnum,size[E.to[i]]);
    	}
    	size[u]++; maxnum=max(maxnum,num-size[u]);
    	if(maxnum<rootnum) root=u,rootnum=maxnum;
    }
    long long calc(int s,int len){
    	long long ret=0;
    	static int dis[MAXN],A[MAXN],reach[MAXN],rnt,ant;
    	static queue<int>Q;
    	ant=0; rnt++; Q.push(s);
    	dis[s]=len; reach[s]=rnt;
    	while(!Q.empty()){
    		int u=Q.front(); Q.pop(); A[++ant]=dis[u];
    		for(int i=E.head[u];i;i=E.nxt[i]){
    			int v=E.to[i];
    			if(reach[v]==rnt||vis[v]) continue;
    			dis[v]=dis[u]+E.val[i];
    			reach[v]=rnt; Q.push(v);
    		}
    	}
    	sort(A+1,A+ant+1);
    	int l=1,r=ant;
    	while(l<=r){
    		if(A[l]+A[r]>K) r--;
    		else ret+=r-l,l++;
    	}
    	return ret;
    }
    void divide(int u){
    	int root=u,rootnum=size[u];
    	getroot(u,0,size[u],root,rootnum);
    	vis[root]=1;
    	ANS+=calc(root,0);
    	for(int i=E.head[root];i;i=E.nxt[i]) if(!vis[E.to[i]])
    		ANS-=calc(E.to[i],E.val[i]);
    	for(int i=E.head[root];i;i=E.nxt[i]) if(!vis[E.to[i]])
    		divide(E.to[i]);
    }
    void read(int &x){
    	static int sign; static char ch;
    	x=0; sign=1; ch=getchar();
    	while(ch<'0'||'9'<ch){if(ch=='-')sign=-1;ch=getchar();}
    	while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	x=x*sign;
    }
    int main(){
    	while(1){
    		read(N); read(K);
    		if(!N&&!K) break;
    		E.Reset(); ANS=0;
    		memset(vis,0,sizeof(vis));
    		for(int i=1,u,v,w;i<N;i++)
    			read(u),read(v),read(w),E.Adde(u,v,w);
    		size[1]=N; divide(1);
    		printf("%lld
    ",ANS);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    JS LeetCode 1423. 可获得的最大点数简单题解
    SpringBoot 学集 (第六章) Docker
    Linux 学记 (第三章)
    Linux 学记 (第二章)
    Linux 学记 (第一章)
    SpringBoot 学集 (第五章) Web开发续
    SpringBoot 学集 (第四章)Web开发
    SpringBoot 学集 (第三章) 日志框架
    SpringBoot 学集 (第二章) 配置文件
    SpringBoot 学集 (第一章)
  • 原文地址:https://www.cnblogs.com/zj75211/p/8541904.html
Copyright © 2020-2023  润新知