「NOIP2014」「Codevs3728」 联合权值(乱搞
3728 联合权值
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
题目描述 Description
输入描述 Input Description
输出描述 Output Description
样例输入 Sample Input
样例输出 Sample Output
数据范围及提示 Data Size & Hint
题解
这(在洛谷上)都是些什么标签?LCA?dp?(MAX问号脸
随意钦定一个点当根节点,转化成有根树处理。
对于dfs到的每个点,$sum$加上$x$和$fa[fa[x]]$的点权乘积$*2$($(x,y)$和$(y,x)$要算两次
然后在当前这个点的所有儿子之间乘一下,加到$sum$里。
当然也顺手跟$mac$取个$max$。
然后在处理每个点的儿子之间的恩怨时,很多人用的是$O(n^2)$的两个for。
菊花图会直接让你们TLE的啊qwq,但是这数据蛮水的,没卡他们qaq
所以我写的时候怕T,做了一丢丢优化,搞到了$O(n)$。
反正也没什么用就是了。
1 /* 2 qwerta 3 P1351 联合权值 4 Accepted 5 100 6 代码 C++,1.41KB 7 提交时间 2018-10-09 11:26:08 8 耗时/内存 9 170ms, 7356KB 10 */ 11 #include<iostream> 12 #include<cstdio> 13 #include<cmath> 14 using namespace std; 15 const int MAXN=200000+3; 16 struct emm{ 17 int e,f; 18 }a[2*MAXN]; 19 int h[MAXN]; 20 int tot=0; 21 void con(int u,int v) 22 { 23 a[++tot].f=h[u]; 24 h[u]=tot; 25 a[tot].e=v; 26 a[++tot].f=h[v]; 27 h[v]=tot; 28 a[tot].e=u; 29 return; 30 } 31 int w[MAXN]; 32 int d[MAXN],fa[MAXN]; 33 const int mod=10007; 34 long long sum=0,ans=0; 35 int st[MAXN]; 36 void dfs(int x) 37 { 38 if(fa[fa[x]]) 39 { 40 sum+=2*w[x]*w[fa[fa[x]]]; 41 sum%=mod; 42 ans=max(ans,(long long)w[x]*w[fa[fa[x]]]); 43 } 44 int tos=0; 45 long long sumn=0; 46 int mac1=0,mac2=0; 47 for(int i=h[x];i;i=a[i].f) 48 if(!d[a[i].e]) 49 { 50 fa[a[i].e]=x; 51 d[a[i].e]=d[x]+1; 52 st[++tos]=a[i].e; 53 sumn+=w[a[i].e]; 54 if(w[a[i].e]>=mac1){mac2=mac1,mac1=w[a[i].e];} 55 else if(w[a[i].e]>mac2){mac2=w[a[i].e];} 56 } 57 ans=max(ans,(long long)mac1*mac2); 58 for(int i=1;i<=tos;++i) 59 { 60 sum+=(sumn-w[st[i]])*w[st[i]]; 61 sum%=mod; 62 } 63 //cout<<x<<" "<<ans<<" "<<sum<<endl; 64 for(int i=h[x];i;i=a[i].f) 65 if(fa[a[i].e]==x) 66 dfs(a[i].e); 67 return; 68 } 69 int main() 70 { 71 //freopen("a.in","r",stdin); 72 int n; 73 scanf("%d",&n); 74 for(int i=1;i<n;++i) 75 { 76 int u,v; 77 scanf("%d%d",&u,&v); 78 con(u,v); 79 } 80 for(int i=1;i<=n;++i) 81 scanf("%d",&w[i]); 82 int s=min(n,7); 83 d[s]=1; 84 dfs(s); 85 cout<<ans<<" "<<sum%mod; 86 return 0; 87 }