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;
    }
    
  • 相关阅读:
    LeetCode题解之Flipping an Image
    LeetCode 之Find Minimum in Rotated Sorted Array
    LeetCode题解Transpose Matrix
    LeetCode 题解之Minimum Index Sum of Two Lists
    LeetCode题解之Intersection of Two Linked Lists
    LeetCode 题解之Add Two Numbers II
    LeetCode题解之Add two numbers
    href="#"与href="javascript:void(0)"的区别
    有关ie9 以下不支持placeholder属性以及获得焦点placeholder的移除
    ie7下属性书写不规范造成的easyui 弹窗布局紊乱
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/LOJ6159.html
Copyright © 2011-2022 走看看