codeforces gym100519 problemG Genealogy(topu)

鏈接

題意:

給出n個人以及他的父親,詢問家族關係中最長的一條鏈,可以有環。



思路:

每個人的兒子可以有多個,但是父親只有一個或者沒有。先考慮簡單的情況,沒有環的話,就類似於森林,建一條兒子指向父親的單向邊,從葉子出發topu,記錄一下每個點向下延申的最大距離即可。如果有環的話,不難發現,環上掛着的鏈的方向都是指向環的,答案就會變爲環的周長+掛着的最長的一條鏈的長度。和之前一樣從葉子topu,環上有鏈的點都記錄了該點所鏈的最大長度,topu結束後,dfs遍歷環統計一下環的周長和最長鏈。



#include <bits/stdc++.h>

#define  _debug(x) cerr<<#x << " = " << x<<endl
using namespace std;

typedef long long ll;
//typedef _int128 lll;
const int MOD = 0;
//const double eps = 1e-3;
const int MAXN = 200000 + 59;
const int INF = 0x3f3f3f3f;
const ll INFll = 0x3f3f3f3f3f3f3f;
const double eps = 1e-9;

unordered_map<string, int> id;
int n, m, ans;
int ind[MAXN];
string sn, fn1, _son, _of, fn2;

struct Edge {
    int v, nx;
} ed[MAXN << 2];

int head[MAXN], cntEd;

void addEdge(int u, int v) {
    ed[cntEd] = {v, head[u]};
    head[u] = cntEd++;
}

int val[MAXN];
queue<int>q;
bool out[MAXN];
void topu(){
    while (!q.empty()){
        int u=q.front();
//        printf("u:%d\n",u);
        out[u]= true;
        q.pop();
        for(int i=head[u];~i;i=ed[i].nx){
            int v=ed[i].v;
            ind[v]--;
            val[v]=max(val[v],val[u]+1);
            ans=max(ans,val[v]);
            if(!ind[v]){
                q.push(v);
            }
        }
    }
}

int tmp;
int r;
void dfs(int u){
    out[u]=true;
    tmp=max(tmp,val[u]);
    r++;
    for(int i=head[u];~i;i=ed[i].nx){
        int v=ed[i].v;
        if(out[v])continue;
        dfs(v);
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    memset(head, -1, sizeof head);
    cntEd = 0;

    cin >> n;
    for (int i = 1, u, v; i <= n; ++i) {
        cin >> sn >> fn1 >> _son >> _of >> fn2;
        fn1 = sn + fn1;
        fn2 = sn + fn2;
        if (!id[fn1])id[fn1] = ++m;
        if (!id[fn2])id[fn2] = ++m;

        v = id[fn1];
        u = id[fn2];
        addEdge(v, u);
        ind[u]++;
    }
    ans=1;
    for(int i=1;i<=m;i++){
        if(!ind[i]){
            q.push(i);
        }
    }
    topu();
//    printf("%d\n",ans);
    for(int i=1;i<=m;i++){
        if(!out[i]){
            tmp=0;
            r=0;
            dfs(i);
//            printf("r:%d\n",r);
            ans=max(ans,tmp+r);
        }
    }
    printf("%d\n",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章