[美团 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 }