函数路径Croc Champ 2013 - Round 2 题解-java教程

发一下牢骚和主题无关:

    目题接链:

    擒贼先擒王,每次赛后总结CF的题,我都爱好先搞E题,而且E题一般是我最爱的数据结构题,搞起来特爽

    E题:给你一棵树,求满意距离之和<=L 且 路径上的权值之和<= w的点对量数。。。

    类似的目题:http://poj.org/problem?id=1741 

    方法是点的分治,详细参考漆子超的论文,分治算法在树的路径中的应用,论文里头经已讲了很详细了

    会了poj 1741的话,其实这道题就是多了一个制限,还是排序,扫描,不过在求的时候须要用树状组数维护一下,其实很简单,不过我还是调试了良久,,,,,代码力能与思维力能都须要精雕细琢啊。

    在求一个二元组序列有多少对满意件条时卡了良久,看大神们都是加了一个0 0进去,我就是不想加,于是越写越烦,不是少算就是多算,最后冷静下来新重想了想,那还是先算成两倍的吧

    我的那个calc函数略挫,,,,

    poj 1741

    

#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int MAX_N = 100010;
struct Edge{
	int b , w;
	Edge() {}
	Edge(int b,int w): b(b),w(w){
	}
};
#define Tr(it,x) for(vector<Edge>::iterator it = x.begin(); it!=x.end();it++)
vector<Edge> edge[MAX_N];
int N , K;
int size[MAX_N]  ;
int opt[MAX_N];
bool del[MAX_N] ;
long long  Ans ;
vector<int>  tnode;
void Dfs(int u,int fa)
{
	tnode.push_back(u);
	opt[u] = 0;
	size[u] = 1;
	Tr(it,edge[u])
	{
		int v = it->b;
		if(!del[v] && v!=fa){
			Dfs(v , u);
			opt[u] = max(opt[u],size[v]);
			size[u] += size[v];	
		}
	}
}
int Find(int u) // find the centre of gravity
{
	Dfs(u,-1);
	int who = -1 , mx = MAX_N;
	for(vector<int>::iterator it = tnode.begin(); it != tnode.end(); it++)
	{
		opt[*it] = max(opt[*it],size[u]-size[*it]);
		if(mx > opt[*it]) {
			mx = opt[*it];
			who = *it;
		}
	}
	return who;
}
vector<int> all , ch[MAX_N];
void Get_dis(int u,int fa,int len,vector<int> &ch)
{
	ch.push_back(len);
	all.push_back(len);
	Tr(it,edge[u])
	{
		if(it->b!=fa && !del[it->b]) {
			Get_dis(it->b,u,len+it->w,ch);
		}
	}
}
long long calc(vector<int> dist) 
{
 	long long ans  = 0;
	int pt = 0 , sz = dist.size();
	sort(dist.begin(),dist.end());
	for(int i = 0,j = sz - 1;i <= j;i++) 
	{
		while(i <= j && dist[i] + dist[j] > K) {
			j--;
		}
		if(i < j) ans += j - i;
	}
	return ans;
}
void Solve(int u)
{
	tnode.clear();
	u = Find(u); // the gravity center 
	all.clear(); // all of the distances
	int nch = 0; // count of sons 
	all.push_back(0);
	Tr(it,edge[u])
	{
		ch[nch].clear(); 
		if(!del[it->b]) Get_dis(it->b,u,it->w,ch[nch++]);
	}	
	Ans += calc(all);
	for(int i = 0; i < nch; i++)  Ans -= calc(ch[i]);	

	del[u] = true;
	Tr(it,edge[u])
		if(!del[it->b])  Solve(it->b);
}
int main()
{
	int a,b,w;
	while(scanf("%d%d",&N,&K),N||K)
	{
		 for(int i = 1; i <= N; i++) edge[i].clear(),del[i]=false;
         for(int i = 1; i < N; i++)
		 {
			 scanf("%d%d%d",&a,&b,&w);
			 edge[a].push_back(Edge(b,w));
			 edge[b].push_back(Edge(a,w));
		 }
		 Ans = 0;
		 Solve(1);
		 printf("%I64d\n",Ans);
	}
	return 0;
}
    每日一道理
生活中受伤难免,失败跌倒并不可怕,可怕的是因此而一蹶不振,失去了对人生的追求与远大的理想。没有一个人的前进道路是平平稳稳的,就算是河中穿梭航行的船只也难免颠簸,生活中所遇上的坎坷磨难不是偶尔给予的为难,而是必然所经受的磨练。

    CROC round2 E

// http://poj.org/problem?id=1741
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int MAX_N = 100010;
struct Edge{
	int b , w;
	Edge() {}
	Edge(int b,int w): b(b),w(w){
	}
};
#define Tr(it,x) for(vector<Edge>::iterator it = x.begin(); it!=x.end();it++)
vector<Edge> edge[MAX_N];
int N , K;
int size[MAX_N]  ;
int opt[MAX_N];
bool del[MAX_N] ;
long long  Ans ;
vector<int>  tnode;
void Dfs(int u,int fa)
{
	tnode.push_back(u);
	opt[u] = 0;
	size[u] = 1;
	Tr(it,edge[u])
	{
		int v = it->b;
		if(!del[v] && v!=fa){
			Dfs(v , u);
			opt[u] = max(opt[u],size[v]);
			size[u] += size[v];	
		}
	}
}
int Find(int u) // find the centre of gravity
{
	Dfs(u,-1);
	int who = -1 , mx = MAX_N;
	for(vector<int>::iterator it = tnode.begin(); it != tnode.end(); it++)
	{
		opt[*it] = max(opt[*it],size[u]-size[*it]);
		if(mx > opt[*it]) {
			mx = opt[*it];
			who = *it;
		}
	}
	return who;
}
vector<pair<int,int> > all , ch[MAX_N];
void Get_dis(int u,int fa,int len,vector<pair<int,int> > &ch,int sum)
{
	ch.push_back(make_pair(sum,len));
	all.push_back(make_pair(sum,len));
	Tr(it,edge[u])
	{
		if(it->b!=fa && !del[it->b]) {
			Get_dis(it->b,u,len+it->w,ch,sum+1);
		}
	}
}
struct BIT{
	int c[MAX_N];
	int maxn ;
	void init(int n) {
		maxn = n;
		memset(c,0,sizeof(int)*n);
	}
	void insert(int x,int d) {
		for(x++;x<=maxn;x+=x&-x) c[x] += d;
	}
	int sum(int x) {
		int ans = 0;
		for(x++;x;x-=x&-x) ans += c[x];
		return ans;
	}
}bit;
int L , W;
int cmp(pair<int,int> a, pair<int,int> b) {
	if(a.second != b.second)return a.second < b.second;
	return a.first < b.first;
}
long long calc(vector<pair<int,int> > d,bool f) //这个函数写挫了,囧
{
 	long long ans  = 0;
	int pt = 0 , sz = d.size();
	int mxd = 0;
	for(int i = 0; i < sz ; i++) {
		mxd = max(mxd,d[i].first);
	}
	bit.init(mxd+2);
	sort(d.begin(),d.end(),cmp);
	int cnt = 0;
	int j = 0;
	for(int i = sz - 1 ; i >= 0; i--) {// cnt : 单个点到根满意件条的个数,独单计统出来
		if(f && d[i].first <= L && d[i].second <= W) cnt++;
		while(j < sz && d[j].second + d[i].second <= W) {
			bit.insert(d[j].first,1);
			j++;
		}
	    if(L >= d[i].first){
			ans += bit.sum(min(mxd,L-d[i].first));
			if(j > i) if(d[i].first+d[i].first <= L) ans --; // 自己 与 自己不能算点对,要去掉
		}
	}
	ans += cnt * 2;
	return ans;
}
void Solve(int u)
{
	tnode.clear();
	u = Find(u); // the gravity center 
	all.clear(); // all of the distances
	int nch = 0; // count of sons 
	Tr(it,edge[u])
	{
		ch[nch].clear(); 
		if(!del[it->b]) Get_dis(it->b,u,it->w,ch[nch++],1);
	}	

	Ans += calc(all,true);
	for(int i = 0; i < nch; i++)  Ans -= calc(ch[i],false);	

	del[u] = true;
	Tr(it,edge[u])
		if(!del[it->b])  Solve(it->b);
}
int main()
{
	int a,b,w;
	while(scanf("%d%d%d",&N,&L,&W)!=EOF)
	{
		 for(int i = 1; i <= N; i++) edge[i].clear(),del[i]=false;
         for(int i = 2; i <= N; i++)
		 {
			 scanf("%d%d",&a,&w);
			 edge[i].push_back(Edge(a,w));
			 edge[a].push_back(Edge(i,w));
		 }
		 Ans = 0;
		 Solve(1);
		 printf("%I64d\n",Ans/2);
	}
	return 0;
}

文章结束给大家分享下程序员的一些笑话语录: 很多所谓的牛人也不过如此,离开了你,微软还是微软,Google还是Google,苹果还是苹果,暴雪还是暴雪,而这些牛人离开了公司,自己什么都不是。

posted @ 2013-04-24 13:43  坚固66  阅读(173)  评论(0编辑  收藏  举报