联合权值

*已更新。

 

原题链接:https://www.luogu.org/problem/show?pid=1351

据说这道题模拟就行?

那为啥标签写着LCA和dp。。

我觉得正常向做法应该就是搜索+剪枝,搜索的时候顺带记录最大联合权值和总和就好。

看一眼题后就写了一暴力,死活A不了,无奈之下看了题解,发现题解有一个奇怪的做法:

 1 #include <iostream>
 2 #include <cstdio>
 3 #define maxn 200005
 4 #define INF 2147483647
 5 #define mo 10007
 6 using namespace std;
 7 struct Edge{
 8     int from,to;
 9 };
10 Edge edge[maxn * 2];
11 int head[maxn];
12 int tot = 0;
13 int pointw[maxn];
14 int n,maxw,sumw;
15 
16 void add_edge(int from,int to){
17     edge[++tot].from = head[from];
18     edge[tot].to = to;
19     head[from] = tot;
20 }
21 
22 int main(){
23     scanf("%d",&n);
24     for (int i=1;i<n;i++){
25         int u,v;
26         scanf("%d%d",&u,&v);
27         add_edge(u,v);
28         add_edge(v,u);
29     }
30     for (int i=1;i<=n;i++)
31         scanf("%d",&pointw[i]);
32 
33     for (int u=1;u<=n;u++){
34         int sum = 0;
35         int ma = 0;
36         int m = 0;
37         for (int i=head[u];i!=0;i=edge[i].from){
38             if (pointw[edge[i].to] > ma){
39                 m = ma;
40                 ma = pointw[edge[i].to];
41             }
42             else
43             if (pointw[edge[i].to] > m)
44                 m = pointw[edge[i].to];
45 //            cout << "i = " << i << endl;
46 //            cout << "m = " << m << endl;
47 //            cout << "ma = " << ma << endl;
48             sumw = (sumw + sum * pointw[edge[i].to]) % mo;
49 //          cout << "sumw = " << sumw << endl;
50             sum = (sum + pointw[edge[i].to]) % mo;
51 //          cout << "sum = " << sum << endl;
52 //          cout << "---" << endl;
53         }
54         maxw = max(maxw,ma*m);
55     }
56 
57 
58     cout << maxw << " " << (sumw*2) % mo;
59     return 0;
60 }

  其实是这样的,注意到对于任意两个距离为2的点, 它们中间必有一个中间点。而这个做法是从中间点入手,枚举所有的中间点,这样中间点的两边就是联合权值,然后分别记录最大值和总值就好。ma和m记录的其实是对于一个中间点所相连的两个点的权值。这个做法正确性显然。

  还是大佬多啊。。我该弱的还是弱。。

转载于:https://www.cnblogs.com/OIerShawnZhou/p/7512843.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值