1. 程式人生 > >美團CODEM 最長樹鏈 列舉質因數,DFS或者直接BFS

美團CODEM 最長樹鏈 列舉質因數,DFS或者直接BFS

題意:樹鏈是指樹裡的一條路徑。美團外賣的形象代言人袋鼠先生最近在研究一個特殊的最長樹鏈問題。現在樹中的每個點都有一個正整數值,他想在樹中找出最長的樹鏈,使得這條樹鏈上所有對應點的值的最大公約數大於1。請求出這條樹鏈的長度。

解法:列舉每個約數,保留對應的邊,做一次最長路徑。因為一個數的約數個數可以保證,所以複雜度符合要求。

下面是官方題解給的程式碼:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cmath>
#include <iostream> #include <algorithm> #include <map> #include <vector> using namespace std; int n, l, c[100001], len, value[100001], visit[100001], V[100001]; bool b[100001]; map< int, vector<int> > factor; struct node{ node *next; int where; } a[200001], *first[100001]; inline void makelist(int
x, int y) { a[++l].where = y; a[l].next = first[x]; first[x] = &a[l]; } pair<int, int> bfs(int init, int v, int round) { c[1] = init; visit[init] = 1; int pos = 0, will = 0; int k = 1, l = 1; for (; l <= k; ++l) { int m = c[l]; if (visit[m] > will) will = visit[m], pos = m; for
(node *x = first[m]; x; x = x->next) if (!(value[x->where] % v) && !visit[x->where]) { visit[x->where] = visit[m] + 1; c[++k] = x->where; } } if (round == 0) for (int i = 1; i <= k; i++) visit[c[i]] = 0; return make_pair(pos, will); } int calc(int v) { vector<int> idx = factor[v]; int will = 0; for (int i = 0; i < idx.size(); i++) if (!visit[idx[i]]) { will = max(will, bfs(bfs(idx[i], v, 0).first, v, 1).second); } for (int i = 0; i < idx.size(); i++) visit[idx[i]] = 0; return will; } int main() { len = 0; memset(b, false, sizeof(b)); for (int i = 2; i <= 100000; i++) { if (!b[i]) c[++len] = i; for (int j = 1; j <= len; ++j) if (c[j] * i > 100000) break; else { b[c[j] * i] = true; if (!(i % c[j])) break; } } scanf("%d", &n); memset(first, 0, sizeof(first)); l = 0; for (int i = 1; i < n; i++) { int x, y; scanf("%d%d", &x, &y); makelist(x, y); makelist(y, x); } factor.clear(); for (int i = 1; i <= n; i++) { int x; scanf("%d", &x); value[i] = x; for (int j = 1; c[j] * c[j] <= x; ++j) if (!(x % c[j])) { if (factor.find(c[j]) == factor.end()) factor[c[j]].clear(); factor[c[j]].push_back(i); for (; !(x % c[j]); ) x /= c[j]; } if (x != 1) { if (factor.find(x) == factor.end()) factor[x].clear(); factor[x].push_back(i); } } int ans = 0; memset(visit, 0, sizeof(visit)); memset(V, 0, sizeof(V)); for (map< int, vector<int> >::iterator itr = factor.begin(); itr != factor.end(); ++itr) ans = max(ans, calc(itr->first)); printf("%d\n", ans); }

然後還看到了一種直接BFS爆搜莽過去的,能過簡直玄學。

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <iostream>
#include <iostream>  
#include <cmath>  
#include<cstdio>  
#include<cstring>  
#include <algorithm>
#include <cctype>
#include <utility>
#include <map>
#include <string>
#include <cstdlib>
#include <queue>
#include <numeric>
#include <vector>
#include<set>
#include <cctype>
using namespace std;
const int maxn = 100050;
int maxlen = 0;
int rd[maxn];
int a[maxn];
vector<int>v[maxn];
inline bool scan(int &ret) {
    char c; int sgn;
    if (c = getchar(), c == EOF) return 0; //EOF  
    while (c != '-' && (c<'0' || c>'9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return 1;
}
struct node {
    int x;
    int len;
    int gcd;
};
void bfs(int x, int len, int gcd)
{
    node n1, n2;
    queue<node>q;
    n1.x = x;
    n1.len = len;
    n1.gcd = gcd;
    q.push(n1);
    while (!q.empty())
    {
        node n1 = q.front();
        q.pop();
        int nx = n1.x;
        int nlen = n1.len;
        int ngcd = n1.gcd;

        maxlen = max(nlen, maxlen);
        for(int i=0;i<v[nx].size();i++)
        {
            int next = v[nx][i];
            int usegcd = __gcd(a[next], ngcd);
            if (usegcd == 1)
            {
                n2.gcd = a[next];
                n2.len = 1;
                n2.x = next;
                q.push(n2);
            }
            else
            {
                n2.gcd = usegcd;
                n2.len = 1+nlen;
                n2.x = next;
                q.push(n2);
            }
        }
    }
}/*
void dfs(int x, int len,int gcd)
{
    maxlen = max(len, maxlen);
    for (int i = 0; i < v[x].size(); i++)
    {
        int next = v[x][i];
        int usegcd = __gcd(a[next], gcd);
        if (usegcd ==1)
            dfs(next, 1, a[next]);
        else
            dfs(next, len+1, usegcd);
    }

}*/
int main()
{

    int n;
    scan(n);
    for (int i = 2; i <= n; i++)
    {
        int a, b;
        scan(a);
        scan(b);
        v[a].push_back(b);
        rd[b]++;
    }
    int go = 0;
    for (int i = 1; i <= n; i++)
    {
        if (rd[i] == 0)
            go = i;
        scan(a[i]);
    }

    bfs(go,1,a[go]);

    printf("%d", maxlen);
    return 0;
}