index饿了,她要找大妈做饭,可是大妈早在错综复杂的学院都市的一处跟炮姐(jq),学院都市是个无向连通图,游走状态的index想要知道对于所有当麻可能在的地点和自己每个游走的地点,平均距离是多少
一句话题意
给定一个含n个点的无向连通图,任意两点间有且仅有一条路径,求两点间距离的平均值,即 ∑disij/(n*n-n) (1≤i≤n,1≤j≤n)
第一行一个正整数n
随后n-1行每行3个正整数a b c,表示a b两点间有一条长度为c的边
输出两点间平均距离,保留两位小数。
4
1 2 1
2 3 1
2 4 1
1.50
40%数据中n≤200
60%数据中n≤2000
100%数据中n≤20000
边的长度≤10000
题目大意如下
树上有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数组检验是否为父亲的方法显然要拙劣很多
先把我的代码放上吧:
//D
#include
#include
#include
using namespace std;
const int maxn=40000+10;
int n,ne;
int p[maxn];
double dp[maxn];
int head[maxn];
struct node
{
int from,to,next,v;
}e[maxn];//e is edge
void add(int u,int v,int w)
{
ne++;
e[ne].from=u;
e[ne].to=v;
e[ne].v=w;
e[ne].next=head[u];
head[u]=ne;
}
/*
int dfs(int root)
{
int et=head[root];
int ans=0;
while (et!=0)
{
if (!visit[e[et].to])
{
visit[e[et].to]=1;
p[e[et].to]=dfs(e[et].to);
ans+=p[e[et].to];
}
et=e[et].next;
}
ans++;
return ans;
}
*/
void dfs(int root,int f=0)
{
p[root]=1;
int et=head[root];
while (et!=0)
{
if (e[et].to!=f)
{
dfs(e[et].to,root);
p[root]+=p[e[et].to];
dp[root]+=dp[e[et].to]+p[e[et].to]*(n-p[e[et].to])*(double)e[et].v;
}
et=e[et].next;
}
return;
}
int main()
{
freopen("1.txt","r",stdin);
//freopen("D.out","w",stdout);
scanf("%d",&n);
int u,v,w;
memset(head,0,sizeof(head));
for (int i=1;i
接下来贴上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 因此即使算法正确 实现起来问题还是很大 细节处理上也还是漏洞很多 而且代码能力还需要进一步提高
所以还是要加油啊···
——纸上得来终觉浅,绝知此事要躬行