[noip2014 d1t2] 联合权值
感觉自己越来越弱了...
对于60%的数据,朴素枚举即可
对于100%的数据,考虑优化
我们注意到每条边的长度均为1,而要求点对距离为2,可见和同一个点有连边的两点之间就会产生权值
对于第一问,显然可以贪心保存最大和次大值从而避免n³的查询;
对于第二问,一个讲的清楚的-->链接
记sum为与一个结点相连的所有点的权值之和,则对于与之相连的每个点i,由结合律,它对答案的贡献就是w[i]*(sum-w[i])
抓住题目的特殊条件,从分析数据间的关系入手,便可有效地避免冗杂的运算,将时间复杂度降在O(k*n),k为较小的常数
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #define maxn 200200 5 #define MOD 10007 6 using namespace std; 7 int n; 8 int weight[maxn]; 9 vector<int> con[maxn]; 10 int read(){ 11 int x=0,f=1; 12 char ch=getchar(); 13 while (ch<'0'||ch>'9'){ 14 if (ch=='-') f=-1; 15 ch=getchar(); 16 } 17 while (ch>='0'&&ch<='9'){ 18 x=x*10+ch-'0'; 19 ch=getchar(); 20 } 21 return x*f; 22 } 23 int main(){ 24 int ans1=0,ans2=0; 25 n=read(); 26 for (int i=1;i<n;i++){ 27 int u=read(),v=read(); 28 con[u].push_back(v); 29 con[v].push_back(u); 30 } 31 memset(weight,0,sizeof(weight)); 32 for (int i=1;i<=n;i++) 33 weight[i]=read(); 34 for (int i=1;i<=n;i++){ 35 int m1=0,m2=0,sum=0; 36 for (int j=0;j<con[i].size();j++){ 37 if (weight[con[i][j]]>=m1){ 38 m2=m1;m1=weight[con[i][j]]; 39 } 40 else if (weight[con[i][j]]>m2){ 41 m2=weight[con[i][j]]; 42 } 43 sum+=weight[con[i][j]]; 44 } 45 sum%=MOD; 46 ans1=max(ans1,m1*m2); 47 for (int j=0;j<con[i].size();j++){ 48 ans2+=(weight[con[i][j]]*(sum-weight[con[i][j]]))%MOD; 49 ans2=(ans2+MOD)%MOD; 50 } 51 } 52 printf("%d %d\n",ans1,ans2); 53 return 0; 54 }
黄学长树规的做法也值得借鉴