您的位置:首页 > 其它

【日常学习】【树形DP】codevs3023 魔法禁书目录1:追捕大妈题解

2015-09-12 16:26 295 查看
题目描述 Description

index饿了,她要找大妈做饭,可是大妈早在错综复杂的学院都市的一处跟炮姐(jq),学院都市是个无向连通图,游走状态的index想要知道对于所有当麻可能在的地点和自己每个游走的地点,平均距离是多少
一句话题意
给定一个含n个点的无向连通图,任意两点间有且仅有一条路径,求两点间距离的平均值,即 ∑disij/(n*n-n) (1≤i≤n,1≤j≤n)

输入描述 Input Description

第一行一个正整数n
随后n-1行每行3个正整数a b c,表示a b两点间有一条长度为c的边

输出描述 Output Description

输出两点间平均距离,保留两位小数。

样例输入 Sample Input

4
1 2 1
2 3 1
2 4 1

样例输出 Sample Output

1.50

数据范围及提示 Data Size & Hint

40%数据中n≤200
60%数据中n≤2000
100%数据中n≤20000
边的长度≤10000

这是我们组内互测时TY君给的题目 我的代码总之是怎么样都过不了的 搜索过程我放在注释里了 哪位神仙能看明白的话烦请不吝指教 鄙人实在蒟蒻···

题目大意如下

树上有n个节点(n<=两万) 给你任意两点间距离 输出平均距离

直接枚举肯定超时,一个好的思路是:

边两端的点数分别为A和B,这条边被经过的次数就是A*B,

它对总的距离和的贡献就是(A*B*此边长度)

求和再除以总路径数N*(N-1)/2

那么就是求每条边两端点的个数 计算一次dfs解决

任取一点为根,在dfs的过程中,对每个点k记录其子树包含的点数(包括其自身)

设点数为a[k],则k的父亲一侧的点数即为N-a[k] 注意乘的时候应该改一改

统计和遍历同时进行 故时间复杂度为O(n)

但是我想我应该是在DFS和最后对边的处理出问题了 TY君的数据都过了 但是codevsA3W7 于是参照着TY君的代码改了一下 最终A了

我们不同之处在于,TY写的显然是树形DP这样子的,一边DFS一边处理 而我是最后扫一遍边集中处理 另外TY君的搜索父子关系很分明,而我用visit数组检验是否为父亲的方法显然要拙劣很多

先把我的代码放上吧:

接下来贴上TY的,很简短,用vector存图···虽然我并没有看懂,但是结构体中构造器的运用是很好的

#include<bits/stdc++.h>
using namespace std;
struct edge{
	int from,to,dis;
	edge(){};
	edge(int x,int y,int z){
		from=x,to=y,dis=z;
	}
};
vector<edge>es;
vector<int>G[20005];
int size[20005];
double dp[20005];
int cnt,n;
void add(int u,int v,int w){
	es.push_back(edge(u,v,w));
	G[u].push_back(es.size()-1);
}
void dfs(int u,int f=0){
	size[u]=1;
	for(int i=0;i<G[u].size();++i){
		edge& x=es[G[u][i]];
		if(x.to==f)continue;
		dfs(x.to,u);
		size[u]+=size[x.to];
		dp[u]+=dp[x.to]+size[x.to]*(n-size[x.to])*(double)x.dis;
	}
}
int main(){
	freopen("D.in","r",stdin);
	freopen("D.out","w",stdout); 
	scanf("%d",&n);
	for(int i=1,a,b,c;i<n;++i){
		scanf("%d%d%d",&a,&b,&c);
		add(a,b,c);
		add(b,a,c);
	}
	dfs(1);
	int s=(n*n-n)/2;
	printf("%.2lf\n",(double)dp[1]/s);
}


这次比赛真是惨不忍睹,如果这是NOIP我们可怎么办才好,四百分的题目我才60分

想想第一题,应该算是算法不对 第二题正解是DP 第三题是递推高精 这两道题都没想到 然而至少写个搜索还能得点分数 第三题没想到的原因主要是看题之后没能理清思路找规律吧 第四题 应该说我搜索的思路还是不清晰,没有算法的完整框架,没有想到这是一个树形DP 因此即使算法正确 实现起来问题还是很大 细节处理上也还是漏洞很多 而且代码能力还需要进一步提高

所以还是要加油啊···

——纸上得来终觉浅,绝知此事要躬行
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: