loj10155. 「一本通 5.2 例 3」数字转换

思路:

  树形dp求最长链。

#include<cstdio>
#include<iostream>
#include<cstdlib>
using namespace std;
const int maxn = 100010;
void qread(int &x){
    x = 0;
    register int ch = getchar();
    while(ch < '0' || ch > '9')    ch = getchar();
    while(ch >= '0' && ch <= '9')    x = 10 * x + ch - 48, ch = getchar();
}
int n, rt;
int head[maxn];
int go[maxn << 1];
int nxt[maxn << 1];

int d1[maxn];
int d2[maxn];

int f[maxn];
int deep[maxn];

int sum[maxn];

void dfs(int x){
    for(int i = head[x]; i; i = nxt[i])
        if(!deep[i]){
            f[go[i]] = x;
            deep[go[i]] = deep[x] + 1;
            dfs(go[i]);
        }
}
inline void init(){
    qread(n);
    for(int i=1; i<=n; ++i)
        for(int j=2; j<=n/i; ++j){
            if(i * j > n)    break;
            sum[i * j] += i;    
        }
    for(int i=1; i<=n; ++i){
        if(sum[i] < i){
            go[i] = sum[i];
            nxt[i] = head[i];
            head[i] = i;
            go[i + n] = i;
            nxt[i + n] = head[sum[i]];
            head[sum[i]] = i + n;
        }
        else{
            go[i] = 0;
            nxt[i] = head[i];
            head[i] = i;
            go[i + n] = i;
            nxt[i + n] = head[0];
            head[0] = i + n;
        }
    }
    rt = 0;
    deep[rt] = 1;
    dfs(rt);                
}

void DP(int x){
    for(int i=head[x]; i; i=nxt[i]){
        if(go[i] != f[x]){
            DP(go[i]);
            if(d1[go[i]] + 1 > d1[x]){
                d2[x] = d1[x];
                d1[x] = d1[go[i]] + 1;
            }
            else if(d1[go[i]] + 1 > d2[x])
                d2[x] = d1[go[i]] + 1;
        }
    }
}
int main(void){
    init();
    DP(rt);
    int ans = 0;
    for(int i = head[rt]; i; i = nxt[i])
        ans = max(ans, d1[go[i]] + d2[go[i]]);
    printf("%d\n", ans);    
}

猜你喜欢

转载自www.cnblogs.com/junk-yao-blog/p/9491375.html