• 洛谷1351 联合权值


    洛谷1351 联合权值


    原题链接


    交题记录

    20:47 第1次提交 70'
    输入文件无法下载(lg大坑比),下载了输出发现第二问萎了,怀疑是取膜的问题。
    20:50 第2次提交 70'
    我就笑笑不说话。。。两份代码只差了一句取膜,结果新交的时间空间都变大,然后从AWAAAAAWW变成AWAAAWAAWA
    咦,输出爆负了。。。
    取了膜的减一个没取膜的是不是会爆负。。。
    20:53 第三次提交 AC
    把取膜改个位置就A了。。。
    是不是边做题编写博客欧气强些。。。
    望着dalao们100~200+ms而我88ms我好骄傲。。。
    最后吐槽一句这为什么是dp题。。。


    题解

    第一反应

    距离为2的点,只会是两个兄弟,或者一个是另一个的子节点的子节点。

    更进一步:兄弟节点情况的优化

    父子的很好算。
    计算兄弟节点的联合权值?

    • (O(n^2))枚举
    • 还有啥???

    先把(O(n^2))的算法列出来:

    for i := 1 to n
        for j := 1 to n
            if(i<>j)then
                {用w[i]*w[j]更新答案}
    

    别问我为什么用Pascal。。。
    总之,每一个点都会和其他兄弟配对一次。
    所以点(a)对答案的贡献为

    [sum_{i=其他兄弟}w[a]*w[i] ]

    [=w[a]*sum_{i=其他兄弟}w[i] ]

    [=w[a]*(sum_{i=包括a的所有兄弟}w[i]-w[a]) ]

    于是第二问解决了。。。就在这里取膜失误身败名裂。。。
    当然,对于第一问,就是权值最大的两个孩子嘛。。。
    现在怎么优化就显而易见了,然后可以过了。


    Code

    // It is made by XZZ
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define rep(a,b,c) for(rg int a=b;a<=c;a++)
    #define drep(a,b,c) for(rg int a=b;a>=c;a--)
    #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
    #define il inline
    #define rg register
    #define vd void
    typedef long long ll;
    il int gi(){
        rg int x=0,f=1;rg char ch=getchar();
        while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    const int maxn=200100,maxm=maxn<<1;
    int w[maxn];
    int fir[maxn],nxt[maxm],dis[maxm],id;
    il vd add(int a,int b){nxt[++id]=fir[a],fir[a]=id,dis[id]=b;}
    int Max=0,Sum=0,mod=10007;
    il vd dfs(int now,int fa,int grandfa){
        Max=max(Max,w[now]*w[grandfa]);
        Sum=(Sum+w[now]*w[grandfa]*2)%mod;
        int sum=0;
        erep(i,now)if(dis[i]^fa){
            sum+=w[dis[i]];
            dfs(dis[i],now,fa);
        }
        int max1=0,max2=0;
        erep(i,now)if(dis[i]^fa){
            Sum=(Sum+w[dis[i]]*((sum-w[dis[i]])%mod))%mod;
            if(w[dis[i]]>max1)max2=max1,max1=w[dis[i]];
            else if(w[dis[i]]>max2)max2=w[dis[i]];
        }
        Max=max(Max,max1*max2);
    }
    int main(){
        int n=gi(),u,v;
        rep(i,2,n)u=gi(),v=gi(),add(u,v),add(v,u);
        rep(i,1,n)w[i]=gi();
        dfs(1,0,0);
        printf("%d %d
    ",Max,Sum);
        return 0;
    }
    
  • 相关阅读:
    C#控件刷新
    [转载] 尺度不变特征变换匹配算法
    C++ windows 多线程 互斥锁
    堆栈内存申请,以及32位程序内存上限
    dumpbin检查Dll
    CV_Assert
    Linux复习
    操作系统复习
    P/NP问题
    程序
  • 原文地址:https://www.cnblogs.com/xzz_233/p/7425250.html
Copyright © 2020-2023  润新知