NOIP 提高组 2014 联合权值(图论???)
https://www.cnblogs.com/violet-acmer/p/9937201.html
题解:
相关变量解释:
int n; int fa[maxn];//fa[i] : i的父亲节点 int w[maxn];//w[i] : i的权值 long long sum[maxn];//sum[i] : i节点的所有儿子节点的权值和 int maxSon1[maxn];//maxSon1[i] : i节点的所有儿子中权值最大值(如果有超过两个儿子) int maxSon2[maxn];//maxSon2[i] : i节点的所有儿子中权值第二大值(如果有超过两个儿子) vector<int >G[maxn];//存边 vector<int >son[maxn];//son[i] : 记录节点 i 的所有儿子节点
步骤:
(1):先Dfs(u,f)预处理出节点u的父亲节点fa[u],儿子节点son[u],儿子节点的权值和sum[u],以及儿子节点的权值最大的前两个权值maxSon1[u],maxSon2[u];
(2):如果某节点 i 含有两个及以上儿子,则每两个儿子间也可构成长度为 2 的边长,求出节点 i 的儿子节点的联合权值,并判断是否可以更新联合权值的最大值;
(3):求 i 节点与其父亲的父亲节点 j 构成的联合权值,并将其二倍(i 与 j 构成联合权值,同样 j 与 i 也可以构成联合权值,所以需要加入两个)与加入到联合权值之和
中,并判断是否可以更新联合权值的最大值。
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define pb(x) push_back(x) 4 #define mem(a,b) memset(a,b,sizeof(a)) 5 const int maxn=200000+10; 6 const int MOD=10007; 7 8 int n; 9 int fa[maxn]; 10 int w[maxn]; 11 long long sum[maxn]; 12 int maxSon1[maxn]; 13 int maxSon2[maxn]; 14 vector<int >G[maxn]; 15 vector<int >son[maxn]; 16 void addEdge(int u,int v) 17 { 18 G[u].pb(v); 19 G[v].pb(u); 20 } 21 void Dfs(int u,int f) 22 { 23 fa[u]=f; 24 for(int i=0;i < G[u].size();++i) 25 { 26 int to=G[u][i]; 27 if(to != f) 28 { 29 son[u].pb(to); 30 sum[u] += w[to]; 31 if(w[to] > maxSon1[u]) 32 { 33 if(maxSon1[u] > maxSon2[u]) 34 maxSon2[u]=maxSon1[u]; 35 maxSon1[u]=w[to]; 36 } 37 else if(w[to] > maxSon2[u]) 38 maxSon2[u]=w[to]; 39 Dfs(to,u); 40 } 41 } 42 } 43 44 void Solve() 45 { 46 mem(sum,0); 47 mem(maxSon1,0); 48 mem(maxSon2,0); 49 Dfs(1,-1); 50 int maxRes=0; 51 int res=0; 52 for(int i=1;i <= n;++i)//步骤(2) 53 { 54 if(son[i].size() >= 2) 55 { 56 maxRes=max(maxRes,maxSon1[i]*maxSon2[i]); 57 for(int j=0;j < son[i].size();++j) 58 res=res%MOD+((sum[i]-w[son[i][j]])%MOD)*(w[son[i][j]]%MOD); 59 } 60 } 61 for(int i=2;i <= n;++i)//步骤(1) 62 { 63 if(fa[i] != 1) 64 { 65 maxRes=max(maxRes,w[fa[fa[i]]]*w[i]); 66 res=res%MOD+2*w[fa[fa[i]]]*w[i]; 67 } 68 } 69 printf("%d %d\n",maxRes,res%MOD); 70 } 71 int main() 72 { 73 scanf("%d",&n); 74 for(int i=1;i < n;++i) 75 { 76 int u,v; 77 scanf("%d%d",&u,&v); 78 addEdge(u,v); 79 } 80 for(int i=1;i <= n;++i) 81 scanf("%d",w+i); 82 Solve(); 83 }
坑:
步骤(2)的情况刚开始忘了,然后,吃了一发wa.................