这道题瞄了一眼还以为是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; }