poj 2114 还是点分治


跟poj 1114差不多的题。。。求是否存在长为X的路径

开始的时候是vector建边,但是超时了,最后找来找去发现是clear的次数太多了,无奈之下,还是换回朴素建边了,哎,以后数据量大的题还是避免STL吧

自己写的calc函数挫的要死,于是从网上淘了一个清晰的。。。

http://blog.csdn.net/sdj222555/article/details/7908842

#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 22222;
struct Divided_Conquer {
	struct Edge{
		int v , w , next;
		Edge(){}
		Edge(int v,int w): v(v),w(w) {
		}
	}edge[maxn];
	int E ;
	void add_edge(int a,int b,int w)
	{
		edge[E].v = b;
		edge[E].w = w;
		edge[E].next = head[a];
		head[a] = E++;
	}
	int head[maxn];
	bool Del[maxn];
	int N , K;
	int size[maxn] , opt[maxn];
	int tnode[maxn] , tns;
	int all[maxn] , as;
	void Dfs(int u,int f)
	{
		tnode[tns++] = u;
		size[u] = 1;
		opt[u] = 0;
		for(int i=head[u];~i;i=edge[i].next) {
			int v = edge[i].v;
			if(!Del[v] && v != f) {
				Dfs(v,u);
				size[u] += size[v];
				opt[u] = max(opt[u],size[v]);
			}
		}
	}
	int Get_Root(int u)
	{
		tns = 0;
		Dfs(u,-1);
		int mi = maxn , ans = -1;
		for(int i = 0; i < tns; i++){
			opt[tnode[i]] = max(opt[tnode[i]],size[u]-size[tnode[i]]) ;
			if(opt[tnode[i]] < mi) {
				mi = opt[tnode[i]];
				ans = tnode[i];
			}
		}
		return ans;
	}
	void Get_Dis(int u,int len,int fa)
	{
		all[as++] = len;
		for(int i=head[u];~i;i=edge[i].next){
			int v = edge[i].v;
			if(!Del[v] && v != fa) {
				Get_Dis(v,len+edge[i].w,u);
			}
		}
	}
	void Solve(int u)
	{
		u = Get_Root(u);
		int nch = 0;
		Ans += Calc(u,0,true);
		Del[u] = true;
		for(int i=head[u];~i;i=edge[i].next) {
			int v = edge[i].v;
			if(!Del[v]) {
				Ans -= Calc(v,edge[i].w,false);
				Solve(v);
			}
		}
	}
	inline long long Calc(int u,int w,bool f)
	{
		int pt = 0 ;
		long long sum = 0 ;
		as = 0;
		Get_Dis(u,w,-1);
		sort(all,all+as);
		if(f) for(int i = 0; i < as; i++) if(all[i]==K) sum++;//单个点到根
		int i = all[0] ? 0 : 1, j = as - 1;  
		while(i < j) //一对点
		{  
			if(all[i] + all[j] < K) i++;  
			else if(all[i] + all[j] > K) j--;  
			else  
			{  
				if(all[i] == all[j])  
				{  
					sum += (j - i) * (j - i + 1) / 2;  
					break;  
				}  
				int st = i, ed = j;  
				while(all[st] == all[i]) st++;  
				while(all[ed] == all[j]) ed--;  
				sum += (st - i) * (j - ed);  
				i = st, j = ed;  
			}  
		}  
		return sum;
	}
	void Ini()
	{
		int a,b,c;
		fill(head,head+N+1,-1);
		E = 0;
		for(int i = 1; i <= N; i++)
		{
			while(scanf("%d",&a)!=EOF && a)
			{
 				scanf("%d",&b);
				add_edge(i,a,b);
				add_edge(a,i,b);
 			}
		}
		while(scanf("%d",&K)!=EOF && K)
		{
			Ans = 0;
			fill(Del,Del+N+1,false);
			Solve(1);
			if(Ans) printf("AYE\n");
			else printf("NAY\n");
		}
		printf(".\n");
	}
	long long Ans;
}sol;
int main()
{
	while(scanf("%d",&sol.N)!=EOF && sol.N)
	{
		sol.Ini();
	}
	return 0;
}
/*
7
1 2 3
1 3 1
2 4 3
2 5 3
3 6 1
3 7 3
2
*/


你可能感兴趣的:(poj 2114 还是点分治)