【DFS】NOIP2014Day1T2[联合权值]题解

来源:互联网 发布:软件测试简单吗 编辑:程序博客网 时间:2024/06/05 09:34

解题报告

我刚开始竟然天真的只想到了 xfa(fa(x)) 的情况……全国联赛要狗带了……

好像有个很棒的公式可以使用:

2ab=(a+b)2a2b22(ab+ac+bc)=(a+b+c)2a2b2c22(ab+ac+ad+bc+bd+cd)=(a+b+c+d)2a2b2c2d2

那么儿子之间的贡献就可以用这个公式求出来。


然而并不需要这么麻烦,我们直接DFS的时候记录一下之前儿子的总和还有最大值就可以了。

示例程序

#include<cstdio>#include<algorithm>using namespace std;const int maxn=200000,MOD=10007;int n,w[maxn+5],MAX,sum;int E,lnk[maxn+5],nxt[maxn*2+5],son[maxn*2+5];#define Eoln(x) ((x)==10||(x)==13||(x)==EOF)inline char readc(){    static char buf[100000],*l=buf,*r=buf;    if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);    if (l==r) return EOF;return *l++;}inline int readi(int &x){    int tot=0,f=1;char ch=readc(),lst='+';    while ('9'<ch||ch<'0') {if (ch==EOF) return EOF;lst=ch;ch=readc();}    if (lst=='-') f=-f;    while ('0'<=ch&&ch<='9') tot=(tot<<3)+(tot<<1)+ch-48,ch=readc();    return x=tot*f,Eoln(ch);}#define Add(x,y) son[++E]=(y),nxt[E]=lnk[(x)],lnk[(x)]=Einline void AMOD(int &x,int tem) {if ((x+=tem)>=MOD) x-=MOD;}void Dfs(int x,int fa=0,int fafa=0){    int M=0,S=0;if (fafa) MAX=max(MAX,w[fafa]*w[x]),AMOD(sum,w[fafa]*w[x]%MOD);    for (int j=lnk[x];j;j=nxt[j]) if (son[j]!=fa)    {        Dfs(son[j],x,fa);MAX=max(MAX,M*w[son[j]]);AMOD(sum,S*w[son[j]]%MOD);        M=max(M,w[son[j]]);AMOD(S,w[son[j]]);    }}int main(){    freopen("link.in","r",stdin);    freopen("link.out","w",stdout);    readi(n);for (int i=1,x,y;i<n;i++) readi(x),readi(y),Add(x,y),Add(y,x);    for (int i=1;i<=n;i++) readi(w[i]);Dfs(1);    return printf("%d %d\n",MAX,sum*2%MOD),0;}