蓝桥集训之病毒溯源
-
核心思想:树形dp
- 遍历整棵树 dfs返回最长长度 同时记录最长序列下标
- 找到根节点 从根节点开始遍历
-
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 10010; int h[N],e[N],ne[N],idx; int n; int son[N]; bool st[N]; void add(int a,int b) //建树 { e[idx] = b,ne[idx] = h[a],h[a] = idx++; } int dfs(int u) { son[u] = -1; //初始化没有儿子 int res=0; for(int i=h[u];i!=-1;i=ne[i]) { int j = e[i]; int d = dfs(j); if(res < d) res = d,son[u] = j; //新的更优 更新d 同时记录子序列元素 else if(res == d) son[u] = min(son[u] , j); //一样就存下标小的 } return res+1; //加上当前节点 } int main() { cin>>n; memset(h,-1,sizeof h); for(int i=0;i<n;i++) { int b; cin>>b; for(int j=0;j<b;j++) { int x; cin>>x; add(i,x); st[x] = true; //有父节点 } } int root = 0; while(st[root]) root++; //找根节点(没有父节点) int d = dfs(root); //最长长度 printf("%d\n", d); printf("%d ", root); while(son[root] != -1) //最长子序列 { root = son[root]; cout<<root<<" "; } }