• 联合权值(NOIP2014)奇特的模拟。。


    原题传送门

    这道题瞄了一眼还以为是SPFA最短路。

    后面发现距离为2.。

    好像可以枚举中间点来着?

    时间效率O(n*(2n-2))≈O(n^2)

    BOOM!(PS:9018上过了,说明数据太水了。。)

    然后我们看看能不能预处理。。

    第一大和第二大可以预处理233~

    然后sum(中间点的临近点的权值总和)可以预处理。。。

    然后就过了?O(n)

    哦,对了忘记讲算法:

    最大的联合权值就是中间点的临近点的第一大*第二大。。

    所有的联合权值。。

    我们假设有三个点a,b,c 那么联合权值=ab+ac+ba+bc+ca+cb=a(b+c)+b(a+c)+c(a+b)=a(sum-a)+b(sum-b)+c(sum-c);

    然后就可以O(n)啦!

    O(∩_∩)O~~。。

    下面先贴O(n^2)代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define mod 10007
    using namespace std;
    int n,num=0;
    struct edge{
        int to,next;
    }g[400001];
    int head[200001],sum=0;
    int w[200001];
    void ins(int x1,int y1)
    {
        g[++num].next=head[x1];
        head[x1]=num;
        g[num].to=y1;
    }
    void addedge(int x1,int y1)
    {
        ins(x1,y1);
        ins(y1,x1);
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            addedge(x,y);
        }
        for(int i=1;i<=n;i++)
        scanf("%d",&w[i]);
        int ans1=0,ans2=0;
        for(int i=1;i<=n;i++)
        {
            int max1=-1,max2=-1;
            for(int j=head[i];j;j=g[j].next)
            {
                int tmp=w[g[j].to];
                sum+=tmp;
                sum%=mod;
                if(tmp>max1)
                {
                    max2=max1;
                    max1=tmp;    
                }
                else if(tmp>max2)
                {
                    max2=tmp;
                }
            }
            ans1=max(ans1,max1*max2);
            for(int j=head[i];j;j=g[j].next)
            {
                ans2+=(w[g[j].to]*(sum-w[g[j].to]))%mod;
                ans2%=mod;
            }
            sum=0;
        }
        ans2=(ans2+mod)%mod;
        printf("%d %d
    ",ans1,ans2);
        return 0;
    }

    再贴O(N)代码(为啥比上面的还慢。。)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define mod 10007
    using namespace std;
    int n,num=0;
    struct edge{
        int to,from;
    }g[200001];
    int head[200001];
    int w[200001];
    int max1[200001],max2[200001];
    int sum[200001];
    void ins(int x1,int y1)
    {
        g[++num].to=y1;
        g[num].from=x1;
    }
    void work(int q,int r){
        if(w[q]>max1[r])
        {
            max2[r]=max1[r];
            max1[r]=w[q];    
        }
        else if(w[q]>max2[r]) max2[r]=w[q];    
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            ins(x,y);
        }
        for(int i=1;i<=n;i++)
        scanf("%d",&w[i]);
        int ans1=0,ans2=0;
        for(int i=1;i<n;i++)
        {
            int u=g[i].from,v=g[i].to;
            sum[u]=(sum[u]+w[v])%mod;
            sum[v]=(sum[v]+w[u])%mod;
            work(u,v);
            work(v,u);
        }
    
        for(int i=1;i<=n;i++)ans1=max(ans1,max1[i]*max2[i]);
        for(int i=1;i<n;i++)
        {
            int u=g[i].from,v=g[i].to;
            ans2+=(w[u]*(sum[v]-w[u]))%mod;
            ans2%=mod;
            ans2+=(w[v]*(sum[u]-w[v]))%mod;
            ans2%=mod;
        }
        ans2=(ans2+mod)%mod;
        printf("%d %d
    ",ans1,ans2);
        return 0;
    }
  • 相关阅读:
    springboot+mybatis集成多数据源MySQL/Oracle/SqlServer
    向Spring容器中注册组件的方法汇总小结
    使用spring initialization创建SpringBoot项目
    mybatis-generator 的坑我都走了一遍
    初识Jsp,JavaBean,Servlet以及一个简单mvc模式的登录界面
    【Linux】用户只显示$问题
    【Linux】Ubuntu创建用户、删除用户、设置用户密码,root和普通用户切换
    【linux】ubuntu安装ssh
    【整理】【JS】map的基本操作
    【整理】【JS】数组定义、添加、删除、替换、遍历基本操作
  • 原文地址:https://www.cnblogs.com/ghostfly233/p/6855279.html
Copyright © 2020-2023  润新知