3728 联合权值

3728 联合权值

 

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 黄金 Gold
 查看运行结果
 
 
 
 
题目描述 Description

3728 联合权值

输入描述 Input Description

3728 联合权值

输出描述 Output Description

3728 联合权值

样例输入 Sample Input

3728 联合权值

样例输出 Sample Output

3728 联合权值

3728 联合权值

数据范围及提示 Data Size & Hint

3728 联合权值

分类标签 Tags 点此展开 

 
 
本来以为很水的一道mst,结果TLE了3个点
70分代码:
#include<bits/stdc++.h>
using namespace std;
#define N 300100
#define mod 10007
vector<int>g[N];
int n,maxn,ans,w[N],vis[N];
void dfs(int t){//树深了,三重循环会爆时间的 
    if(vis[t]) return ;
    vis[t]=1;
    for(int i=0;i<g[t].size();i++){
        int k=g[t][i];
        for(int j=0;j<g[k].size();j++){
            int h=g[k][j];
            if(h==t) continue;
            int ts=w[t]*w[h];
            maxn=max(maxn,ts);
            ans=(ans%mod+ts%mod)%mod;
        }
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1,x,y;i<n;i++){
        scanf("%d%d",&x,&y);
        g[x].push_back(y);
        g[y].push_back(x);
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&w[i]);
    }
    for(int i=1;i<=n;i++){
        dfs(i);
    }
    printf("%d %d\n",maxn,ans);
    return 0;
}

思路引导:

3728 联合权值

3728 联合权值

 

以上为日照夏令营提供的标解;(有能力者,自己写代码)--在此仅做整理。

以下为自己以前写的代码;

 

优化后AC代码:

题解:

maxn 很显然等于某个点的最大的儿子乘以次大的儿子(有点“贪心”的味道)

ans = w[x] * (sum[fa[x]] - w[x]),fa[x]指的是父亲节点,但是这样会重复计算,所以直接按照dfs序去跑(这里直接循环就好了),计算过的就删去就好了

 

//正解:枚举每个点,这个点所连接的任意两点的距离为2,把它们都放到一个数组里,取最大的两个数相乘即为当前最优解,对于所有点取大;
//至于权值和,补充一个数学知识:(a+b+c)^2=a*a+b*b+c*c+2ab+2ac+2bc, 2ab+2ac+2bc即为当前和,对于所有点取和。
#include<bits/stdc++.h>
using namespace std;
#define N 300100
#define mod 10007
vector<int>g[N];
int n,maxn,ans,w[N];
int main(){
    scanf("%d",&n);
    for(int i=1,x,y;i<n;i++){
        scanf("%d%d",&x,&y);
        g[x].push_back(y);
        g[y].push_back(x);
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&w[i]);
    }
    for(int i=1;i<=n;i++){
        int s=0,p=0;
        int m1=0,m2=0;
        for(int j=0;j<g[i].size();j++){
            int k=w[g[i][j]];
            s=(s+k%mod)%mod;
            p=(p+k*k%mod)%mod;
            if(k>m1) m2=m1,m1=k;
            else if(k>m2) m2=k;
        }
        maxn=max(maxn,m1*m2);
        ans=(ans+(s*s-p)%mod)%mod;
    }
    printf("%d %d\n",maxn,ans);
    return 0;
}