• Luogu P1351 联合权值 题解


    • 这是一个不错的树形结构的题,由于本蒟蒻不会推什么神奇的公式其实是懒得推。。。,所以很愉快的发现其实只需要两个点之间的关系为祖父和儿子、或者是兄弟即可。
    • 然后问题就变得很简单了,只需要做一个正常的DFS,遍历整棵树,同时判断有没有祖父,如果有就计算,然后遍历自己的儿子,每次判断最大的一个,然后用一个(sum)来维护这个点之前的所有兄弟的权值和,挨个计算即可。
    • 具体操作见代码,如果有不懂的,代码里面具体解释。
    #include<bits/stdc++.h>
    #define clean(a,i) memset(a,i,sizeof(a))
    #define ll long long
    #define inl inline
    #define il inl void
    #define it inl int
    #define ill inl ll
    #define re register
    #define ri re int
    #define rl re ll
    #define mod 10007
    using namespace std;
    template<class T>il read(T &x) //快读
    {
    	int f=1;char k=getchar();x=0;
    	for(;k>'9'||k<'0';k=getchar()) if(k=='-') f=-1;
    	for(;k>='0'&&k<='9';k=getchar()) x=(x<<3)+(x<<1)+k-'0';
    	x*=f;
    }
    const int MAXN = 2e5+5;
    int n,u,v,head[MAXN],num_edge,val[MAXN],mx,ans;
    struct Edge{
    	int next,to;
    	Edge(){}
    	Edge(int next,int to):next(next),to(to){} //结构体自带生成函数
    }edge[MAXN<<1]; //结构体用来存边,因为是无向边,所以大小开两倍
    il add_edge(int u,int v){
    	edge[++num_edge]=Edge(head[u],v);head[u]=num_edge;
    	edge[++num_edge]=Edge(head[v],u);head[v]=num_edge;
    } //加边函数
    il DFS(int u,int fa,int gf){ //这道题的主体部分
    	if(gf) mx=max(mx,val[u]*val[gf]),ans=(ans+(val[u]*val[gf])%mod)%mod; //因为gf是从 0 传下来的,所以当gf不等于 0 的时候,说明这个点有祖父了
    	ri maxn=0,sum=0; // maxn 用来存这个点前面的兄弟里面最大的一只, sum 用来存前面的兄弟的权值和
    	for(ri i=head[u];i;i=edge[i].next){
    		if(edge[i].to==fa) continue;
    		DFS(edge[i].to,u,fa); //向下递归,然后从叶节点开始回溯
    		ans=(ans+(sum*val[edge[i].to])%mod)%mod;
    		mx=max(mx,val[edge[i].to]*maxn); // 更新答案
    		sum+=val[edge[i].to];sum%=mod;
    		maxn=max(maxn,val[edge[i].to]); // 更新当前节点的数据
    	}
    }
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	read(n);
    	for(ri i=1;i<n;i++) read(u),read(v),add_edge(u,v); //读入边
    	for(ri i=1;i<=n;i++) read(val[i]); //读入权值
    	DFS(1,0,0); //solve
    	printf("%d %d",mx,(ans*2)%mod); //输出,因为是任意点对,所以答案要乘二
    	return 0;
    }
    
    • 还有一点要注意一下,不知道有没有人注意到我代码里面这句:
    sum%=mod;
    
    • 我这里取模的原因是因为(sum)累加起来,再去和当前节点相乘,可能会超出int的范围,甚至long long也是,要保证答案的正确性,一定要有这一步处理!我自己做的时候就被坑了。。。
    • 希望我这片题解能给一些像我一样的肯定都比我强的蒟蒻一些帮助吧![]( ̄▽ ̄)*
    • 愉快收工!

    顺便安利一下自己的博客 虽然还几乎啥都没有

  • 相关阅读:
    DHCP和NAT
    Mongos WoW
    是否能在构造函数,析构函数中抛出异常?
    Lua Getter/Setter
    xLua
    基于模板特化的Lua自动绑定系统
    为什么有人说富坚义博有着殿堂级的画功?他的画功体现在哪儿呢? 关注者 10205 被浏览 2701670
    在Windows和MacOS下编译Lua
    解决warning MSB8012:问题
    setjmp和longjmp
  • 原文地址:https://www.cnblogs.com/TheShadow/p/10659494.html
Copyright © 2020-2023  润新知