zoukankan      html  css  js  c++  java
  • 【LOJ6159】「美团 CodeM 初赛 Round A」最长树链(树的直径)

    点此看题面

    大致题意: 给定一棵树,每个点有一个点权,求最长链满足链上所有点权(gcd ot=1)

    套路

    首先,看到(gcd),我们可以进行一个套路转化:

    枚举一个质因子,每次只保留点权是这个质因子倍数的点,然后(BFS)求树的直径。

    于是这道题就做完了。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100000
    #define LN 15
    #define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
    using namespace std;
    int n,ans,tg[N+5],vis[N+5],ee,lnk[N+5];struct edge {int to,nxt;}e[2*N+5];
    int cnt;map<int,int> p;vector<int> v[N*LN+5];
    class FastIO
    {
    	private:
    		#define FS 100000
    		#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
    		#define D isdigit(c=tc())
    		char c,*A,*B,FI[FS];
    	public:
    		I FastIO() {A=B=FI;}
    		Tp I void read(Ty& x) {x=0;W(!D);W(x=(x<<3)+(x<<1)+(c&15),D);}
    }F;
    int Pt,P[N+5];I void Sieve()//线性筛预处理,筛质数
    {
    	RI i,j;for(i=2;i<=N;++i) for(!P[i]&&(P[++Pt]=i),
    		j=1;j<=Pt&&1LL*i*P[j]<=N;++j) if(P[i*P[j]]=1,!(i%P[j])) break;
    }
    I void Resolve(CI id,RI x)//分解x
    {
    	#define Pos(x) (p[x]?p[x]:(p[x]=++cnt))
    	for(RI i=1;i<=Pt&&1LL*P[i]*P[i]<=x;++i) if(!(x%P[i])) {v[Pos(P[i])].push_back(id);W(!(x%P[i])) x/=P[i];}
    	x^1&&(v[Pos(x)].push_back(id),0);
    }
    int q[N+5],g[N+5],dis[N+5];I int BFS(CI p,CI x)//BFS
    {
    	static int ti=0;RI i,k,f=0,H=1,T=1;q[1]=x,g[x]=++ti,dis[x]=0;
    	W(H<=T) for(i=lnk[k=q[H++]];i;i=e[i].nxt) g[e[i].to]^ti&&tg[e[i].to]==p&&
    		(vis[e[i].to]=p,g[e[i].to]=ti,(dis[e[i].to]=dis[k]+1)>dis[f]&&(f=e[i].to),q[++T]=e[i].to);
    	return f;
    }
    I void TD(CI p,RI x) {x=BFS(p,x),x=BFS(p,x),ans=max(ans,dis[x]+1);}//树的直径
    int main()
    {
    	RI i,x,y;for(Sieve(),F.read(n),i=1;i^n;++i) F.read(x),F.read(y),add(x,y),add(y,x);
    	RI j,s;for(i=1;i<=n;++i) F.read(x),Resolve(i,x);for(i=1;i<=cnt;++i)//枚举质因子
    	{
    		for(s=v[i].size(),j=0;j^s;++j) tg[v[i][j]]=i;//给包含这个质因子的数打上标记
    		for(j=0;j^s;++j) vis[x=v[i][j]]^i&&(TD(i,x),0);//求树的直径
    	}return printf("%d
    ",ans),0;
    }
    
  • 相关阅读:
    go channel select如何屏蔽已关闭通道
    go err
    在OneNote中快速插入当前日期和时间
    如何查看Isilon节点的硬件信息?
    一个可用来记录Isilon各个节点的CPU,网络,磁盘性能的命令
    Linux中如何查看文件夹的大小
    如何同步两台Linux机器的时间?
    Linux中的硬链接(hard link)和符号连接(symbolic link)
    在Cygwin里,如何进入到C盘?
    Remote Desktop Session中如何触发Ctrl+Alt+Delete?
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/LOJ6159.html
Copyright © 2011-2022 走看看