[美团 CodeM 初赛 Round A]最长树链

题目大意:
  给你一棵带点权的树,找出一个最长的树链满足链上点权的最大公因数不为1。

思路:
  暴力DP。
  对于每个点,记录一下以这个点为一个端点的所有链的最大公因数及长度。
  然后暴力转移一下,时间复杂度O(n^2logn),不过中间有一些情况是可以舍掉的,做不满。
  本来是想试试这样暴力能拿多少分的,没想到直接A掉了。

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<vector>
 4 #include<hash_map>
 5 inline int getint() {
 6     register char ch;
 7     while(!isdigit(ch=getchar()));
 8     register int x=ch^'0';
 9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
10     return x;
11 }
12 const int N=100001;
13 int w[N],ans;
14 std::vector<int> e[N];
15 inline void add_edge(const int &u,const int &v) {
16     e[u].push_back(v);
17     e[v].push_back(u);
18 }
19 int gcd(const int &a,const int &b) {
20     return b?gcd(b,a%b):a;
21 }
22 __gnu_cxx::hash_map<int,int> dfs(const int &x,const int &par) {
23     __gnu_cxx::hash_map<int,int> map,tmp;
24     map[w[x]]=1;
25     for(unsigned i=0;i<e[x].size();i++) {
26         const int &y=e[x][i];
27         if(y==par) continue;
28         tmp=dfs(y,x);
29         for(register __gnu_cxx::hash_map<int,int>::iterator i=map.begin();i!=map.end();i++) {
30             for(register __gnu_cxx::hash_map<int,int>::iterator j=tmp.begin();j!=tmp.end();j++) {
31                 if(gcd(i->first,j->first)!=1) {
32                     ans=std::max(ans,i->second+j->second);
33                 }
34             }
35         }
36         for(register __gnu_cxx::hash_map<int,int>::iterator i=tmp.begin();i!=tmp.end();i++) {
37             const int tmp=gcd(w[x],i->first);
38             if(tmp!=1) {
39                 map[tmp]=std::max(map[tmp],i->second+1);
40             }
41         }
42     }
43     return map;
44 }
45 int main() {
46     const int n=getint();
47     for(register int i=1;i<n;i++) {
48         add_edge(getint(),getint());
49     }
50     for(register int i=1;i<=n;i++) {
51         w[i]=getint();
52     }
53     dfs(1,0);
54     printf("%d\n",ans);
55     return 0;
56 }

 

转载于:https://www.cnblogs.com/skylee03/p/8078469.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值