題意:
給出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;
}