520的信心赛——点点玩deeeep
作者:互联网
3、点点玩 deeeep(deeeep.cpp)
描述
点点最近迷上了 deeeep(此 de 非彼 de),在研究一个特殊的
最长树链问题(树链即树上的一条路径)。现在一棵树中的每个点
都有一个 deeeep 值(正整数)
,点点想在树中找出最长的树链,使
得这条树链上所有对应点的 deeeep 值的最大公约数大于 1。请求出
这条树链的长度。(巨说这道题很 water!
)
格式
输入格式
第 1 行:整数 n(1 ≤ n ≤ 100000),表示点的个数。
第 2~n 行:每行两个整数 x,y 表示 x 和 y 之间有边,数据保证给
出的是一棵树。
第 n+1 行:n 个整数,依次表示点 1~n 对应的权值(1 ≤ 权值 ≤
1,000,000,000)
。
输出格式输出一个整数,表示这条树链的长度。
样例 1
样例输入 1
4
1 2
1 3
2 4
6 4 5 2
样例输出 1
3
限制
对于 100%的数据 1≤n≤100000,1≤ai≤10^9
Solution:
本题考察搜索+数学。
实际上就是乱写暴力。bfs爆搜能ac,还比正解快,简直鬼畜。
枚举每个约数,保留对应的边,做一次最长路径。因为一个数的约数个数可以保证,所以复杂度符合要求。
看起来10^9很虚,但是我们分解质因数只需要预处理出3*10^4里的质数,实际上只有3000多个,3000*n完全不虚,所以我们可以先将n个数全都分解质因数。
然后我们枚举每个质数,枚举所有包含这些质数的点,看一下这些点在树上能形成的最长的链有多长。具体做法是我们将这些点按照深度从大到小排序,然后更新每个点父亲的子树中到父亲的最长链、次长链分别是多长,乱搞一下就行了。
代码:
bfs玄学比正解快:
1 /*莫名打的玄学复杂度bfs,结果ac——by 520*/ 2 #include<bits/stdc++.h> 3 #define il inline 4 using namespace std; 5 const int maxn = 100050; 6 int maxlen=0,rd[maxn],a[maxn]; 7 vector<int>v[maxn]; 8 il int gi() 9 { 10 int a=0;char x=getchar();bool f=0; 11 while((x<'0'||x>'9')&&x!='-')x=getchar(); 12 if(x=='-')x=getchar(),f=1; 13 while(x>='0'&&x<='9')a=a*10+x-48,x=getchar(); 14 return f?-a:a; 15 } 16 struct node{ 17 int x; 18 int len; 19 int gcd; 20 }; 21 il void bfs(int x,int len,int gcd) 22 { 23 node n1,n2; 24 queue<node>q; 25 n1.x=x; n1.len=len; n1.gcd=gcd; 26 q.push(n1); 27 while(!q.empty()) 28 { 29 node n1=q.front(); q.pop(); 30 int nx=n1.x, nlen=n1.len, ngcd=n1.gcd; 31 maxlen=max(nlen, maxlen); 32 for(int i=0;i<v[nx].size();i++) 33 { 34 int next=v[nx][i], usegcd=__gcd(a[next],ngcd); 35 if(usegcd==1){ 36 n2.gcd=a[next]; n2.len=1; n2.x=next; 37 q.push(n2); 38 } 39 else{ 40 n2.gcd=usegcd; n2.len=1+nlen; n2.x=next; 41 q.push(n2); 42 } 43 } 44 } 45 } 46 int main() 47 { 48 freopen("deeeep.in","r",stdin); 49 freopen("deeeep.out","w",stdout); 50 int x,y,n=gi(),go=0; 51 for(int i=2;i<=n;i++) 52 { 53 x=gi(),y=gi(); 54 v[x].push_back(y); 55 rd[y]++; 56 } 57 for(int i=1;i<=n;i++) 58 { 59 if(rd[i]==0)go=i; 60 a[i]=gi(); 61 } 62 bfs(go,1,a[go]); 63 printf("%d",maxlen); 64 return 0; 65 }
正解:
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <vector> 7 #include <map> 8 using namespace std; 9 int n,m,cnt,ans,tot,mor; 10 const int maxn=100010; 11 int to[maxn<<1],nxt[maxn<<1],head[maxn],v[maxn],d1[maxn],d2[maxn],p[103600],fa[maxn],dep[maxn],pri[3600]; 12 bool np[33000]; 13 vector<int> s[103600]; 14 map<int,int> mp; 15 int rd() 16 { 17 int ret=0; char gc=getchar(); 18 while(gc<'0'||gc>'9') gc=getchar(); 19 while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar(); 20 return ret; 21 } 22 void dfs(int x) 23 { 24 for(int i=head[x];i!=-1;i=nxt[i]) if(to[i]!=fa[x]) fa[to[i]]=x,dep[to[i]]=dep[x]+1,dfs(to[i]); 25 } 26 bool cmp1(int a,int b) 27 { 28 return s[a].size()>s[b].size(); 29 } 30 bool cmp2(int a,int b) 31 { 32 return dep[a]>dep[b]; 33 } 34 void updata(int a,int b) 35 { 36 if(d1[b]>d1[a]) d2[a]=d1[a],d1[a]=d1[b]; 37 else d2[a]=max(d2[a],d1[b]); 38 } 39 void add(int a,int b) 40 { 41 to[cnt]=b,nxt[cnt]=head[a],head[a]=cnt++; 42 } 43 int main() 44 { 45 freopen("deeeep.in","r",stdin); 46 freopen("deeeep.out","w",stdout); 47 n=rd(); 48 int i,j,a,b; 49 memset(head,-1,sizeof(head)); 50 for(i=1;i<n;i++) a=rd(),b=rd(),add(a,b),add(b,a); 51 for(i=1;i<=n;i++) v[i]=rd(),m=max(m,v[i]); 52 m=ceil(sqrt(1.0*m)); 53 for(i=2;i<=m;i++) 54 { 55 if(!np[i]) pri[++tot]=i,mp[i]=tot; 56 for(j=1;j<=tot&&i*pri[j]<=m;j++) 57 { 58 np[i*pri[j]]=1; 59 if(i%pri[j]==0) break; 60 } 61 } 62 dep[1]=1,dfs(1),mor=tot; 63 for(i=1;i<=n;i++) 64 { 65 for(j=1;j<=tot&&pri[j]*pri[j]<=v[i];j++) 66 { 67 if(v[i]%pri[j]==0) 68 { 69 s[j].push_back(i); 70 while(v[i]%pri[j]==0) v[i]/=pri[j]; 71 } 72 } 73 if(v[i]>1) 74 { 75 if(mp.find(v[i])==mp.end()) mp[v[i]]=++mor; 76 s[mp[v[i]]].push_back(i); 77 } 78 } 79 ans=1; 80 for(i=1;i<=mor;i++) p[i]=i; 81 sort(p+1,p+mor+1,cmp1); 82 for(i=1;i<=mor;i++) 83 { 84 b=p[i]; 85 if(s[b].size()<=ans) break; 86 sort(s[b].begin(),s[b].end(),cmp2); 87 for(j=0;j<s[b].size();j++) a=s[b][j],d1[a]++,d2[a]++,ans=max(ans,d1[a]+d2[a]-1),updata(fa[a],a); 88 for(j=0;j<s[b].size();j++) a=s[b][j],d1[a]=d2[a]=d1[fa[a]]=d2[fa[a]]=0; 89 } 90 printf("%d",ans); 91 return 0; 92 }
标签:maxn,int,点点,520,n1,include,deeeep,d1 来源: https://blog.51cto.com/u_15180869/2873728