Educational Codeforces Round 58 (Rated for Div. 2) D.GCD Counting(树的直径+gcd)

题意

思路来源

Codeforce__JuRuo

题解

将每个gcd分解素因子放入对应vector

相当于对每个素因子建了一棵树

遍历每个素因子的树,寻找直径,更新答案

注意C++11的写法 好好学学 会省不少功夫

还有一些技巧性写法 加油!

代码

#include<bits/stdc++.h>
using namespace std;
#define ll __int64
const int maxn=2e5+10;
int n,a[maxn],vis[maxn],vis1[maxn],ans=1,flag=1,md,mp,p[maxn];
struct edge
{
   int u,v;
   edge(int uu,int vv):u(uu),v(vv){
   }
};
vector<edge>e[maxn];
vector<int> v[maxn];
void dfs(int p,int d,int *vis)
{
	if(vis[p])return;//溯父 不影响 
	vis[p]=1;
	if(d>md)md=d,mp=p;
	for(int i=0;i<v[p].size();++i)
	dfs(v[p][i],d+1,vis);
} 
int gcd(int a,int b)
{
	return b?gcd(b,a%b):a;
}
int main()
{
	for(ll i=2;i<maxn;++i)
	{
		if(!p[i])
		{
			for(ll j=i*i;j<maxn;j+=i)
			p[j]=1;
		}
	}
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
	{
		scanf("%d",a+i),a[i]>1&&(flag=0);//短路判均<=1 
	} 
	if(flag)
	{
		puts("0");
		return 0; 
	}
	for(int i=1;i<n;++i)
	{
		int u,v,k;
		scanf("%d%d",&u,&v);
		if((k=gcd(a[u],a[v]))>1)
		{
		  for(int j=1;j*j<=k;++j)//j从1开始是为了判k 
		  {
		  	if(k%j==0)
		  	{
		  	if(!p[j]&&j!=1)e[j].push_back(edge(u,v));
		  	if(j*j!=k&&!p[k/j])e[k/j].push_back(edge(u,v));
		    }
		  } 
		} 
	}
	for(int i=2;i<maxn;++i)
	{
		if(!p[i])
		{
			vector<int> p;
			for(int j=0;j<e[i].size();++j)
			{
				edge& E=e[i][j];
				p.push_back(E.u);
				p.push_back(E.v);
				v[E.u].push_back(E.v);
				v[E.v].push_back(E.u);
			}
			for(int j=0;j<p.size();++j)
			{
				vis[p[j]]=vis1[p[j]]=0;
			}
			for(int j=0;j<p.size();++j)
			{
				if(!vis[p[j]])
				{
					md=0;
					dfs(p[j],1,vis);
					md=0;
					dfs(mp,1,vis1);
					ans=max(ans,md);
				}
			}
			for(int j=0;j<p.size();++j)
			v[p[j]].clear(); 
		}
	}
	printf("%d\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Code92007/article/details/86353183
今日推荐