码迷,mamicode.com
首页 > 其他好文 > 详细

●POJ 1741 Tree

时间:2018-03-10 22:10:10      阅读:195      评论:0      收藏:0      [点我收藏+]

标签:name   style   pac   [1]   ret   front   divide   sort   int   

题链:

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\n",ANS);
	}
	return 0;
}

 

  

 

●POJ 1741 Tree

标签:name   style   pac   [1]   ret   front   divide   sort   int   

原文地址:https://www.cnblogs.com/zj75211/p/8541904.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!