向前走莫回头❤

【bzoj 十连测】[noip2016十连测第五场]Problem B: walk(dfs求最长链)

【题解】【DFS+最长链】
【按gcd重新构图,每次选定一个gcd,把所有加入后gcd仍为选定值的边加入树中,dfs求最长路】
【记录每个最长链的gcd。最后从后往前枚举长度,更新每个长度的gcd为最大值(ans[i]=max(ans[i],ans[i+1]))】

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{
    int s,t,nxt;
}mp[400010],a[800010];
int point[1000010],p[400010],link[800010],len[800010];
int ans[400010],maxlen,num,maxn;
int n,tot,cnt;
inline void Add(int x,int y,int val)
{
    tot++; mp[tot].s=x; mp[tot].t=y;
    mp[tot].nxt=point[val]; point[val]=tot;
}
inline void add(int x,int y)
{
    cnt++; a[cnt].s=x; a[cnt].t=y;
    a[cnt].nxt=p[x]; p[x]=cnt; link[cnt]=x;
    cnt++; a[cnt].s=y; a[cnt].t=x;
    a[cnt].nxt=p[y]; p[y]=cnt; link[cnt]=y; 
}
int dfs(int x)
{
    len[x]=num; 
    int maxson=0;
    for(int i=p[x];i;i=a[i].nxt)
     if(len[a[i].t]!=num) 
      {
        int b=dfs(a[i].t);
        maxlen=max(maxlen,maxson+b+1);
        maxson=max(maxson,b+1);
      }
    return maxson;
}
int main()
{
    //freopen("walk.in","r",stdin);
    //freopen("walk.out","w",stdout);
    int i,j;
    scanf("%d",&n);
    for(i=1;i<n;++i)
     {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        Add(x,y,z); maxn=max(maxn,z);
     }
    for(int k=1;k<=maxn;++k)
     {
        for(i=k;i<=maxn;i+=k)
         for(j=point[i];j;j=mp[j].nxt)
          add(mp[j].s,mp[j].t);
        maxlen=0; num++;
        for(i=1;i<=cnt;++i)
          if(len[link[i]]!=num) dfs(link[i]); 
        for(i=1;i<=cnt;++i) p[link[i]]=0;
        cnt=0; ans[maxlen]=k; 
     }
    for(i=n-1;i>0;--i) ans[i]=max(ans[i],ans[i+1]);
    for(i=1;i<=n;++i) printf("%d\n",ans[i]);
    return 0;
}


posted @ 2016-11-17 08:21  lris0-0  阅读(73)  评论(0编辑  收藏  举报
过去的终会化为美满的财富~o( =∩ω∩= )m