• 联赛模拟测试20 B. Walk (建图)


    题目描述


    分析

    一条边只会在枚举它因子作为答案时才有用
    所以,我们考虑从 (1) 到最大值枚举答案 (w),把所有倍数是 (w) 的边连起来
    在形成的森林中跑一个直径
    这样相当于把每条边分成因子个数条边
    注意,你不能一开始就建好图然后在枚举时打标记,这样你走的边会变多
    时间复杂度 (O(n imes sqrt{n}))

    代码

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<ctime>
    #define rg register
    inline int read(){
    	rg int x=0,fh=1;
    	rg char ch=getchar();
    	while(ch<'0' || ch>'9'){
    		if(ch=='-') fh=-1;
    		ch=getchar();
    	}
    	while(ch>='0' && ch<='9'){
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	return x*fh;
    }
    const int maxn=1e6+5;
    int n,h[maxn],tot=1,mmax;
    struct asd{
    	int to,nxt;
    }b[maxn];
    struct jie{
    	int zb,yb;
    	jie(){}
    	jie(int aa,int bb){
    		zb=aa,yb=bb;
    	}
    };
    void ad(int aa,int bb){
    	b[tot].to=bb;
    	b[tot].nxt=h[aa];
    	h[aa]=tot++;
    }
    std::vector<jie> g[maxn];
    int ans[maxn],dis[maxn],sta[maxn],tp,vis[maxn],tim,maxdis,jl,jll;
    void dfs(int now,int fa){
    	vis[now]=tim;
    	for(rg int i=h[now];i!=-1;i=b[i].nxt){
    		rg int u=b[i].to;
    		if(u==fa) continue;
    		dis[u]=dis[now]+1;
    		if(dis[u]>maxdis){
    			maxdis=dis[u];
    			jl=u;
    		}
    		dfs(u,now);
    	}
    }
    int main(){
    	freopen("walk.in","r",stdin);	
    	freopen("walk.out","w",stdout);
    	memset(h,-1,sizeof(h));
    	n=read();
    	rg int aa,bb,cc;
    	for(rg int i=1;i<n;i++){
    		aa=read(),bb=read(),cc=read();
    		g[cc].push_back(jie(aa,bb));
    		if(cc>mmax) mmax=cc;
    	}
    	for(rg int i=1;i<=mmax;i++){
    		tp=0;
    		tot=1;
    		tim++;
    		for(rg int j=i;j<=mmax;j+=i){
    			for(rg int k=0;k<g[j].size();k++){
    				sta[++tp]=g[j][k].zb;
    				sta[++tp]=g[j][k].yb;
    				ad(g[j][k].zb,g[j][k].yb);
    				ad(g[j][k].yb,g[j][k].zb);
    			}
    		}
    		for(rg int j=1;j<=tp;j++){
    			if(vis[sta[j]]!=tim){
    				maxdis=0,jl=0;
    				dis[sta[j]]=0;
    				dfs(sta[j],0);
    				jll=jl;
    				maxdis=0,jl=0;
    				dis[jll]=0;
    				dfs(jll,0);
    				ans[maxdis]=i;
    			}
    		}
    		for(rg int j=1;j<=tp;j++){
    			h[sta[j]]=-1;
    		}
    	}
    	for(rg int i=n;i>=1;i--){
    		ans[i]=std::max(ans[i],ans[i+1]);
    	}
    	for(rg int i=1;i<=n;i++){
    		printf("%d
    ",ans[i]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    python基本数据类型剖析
    常用正则表达式
    python_re模块
    迭代器模式
    状态模式
    备忘录模式
    asp.net 发送邮件
    建造者模式
    抽象工厂模式
    摸板模式与钩子
  • 原文地址:https://www.cnblogs.com/liuchanglc/p/13856818.html
Copyright © 2020-2023  润新知