基环树
一、定义
具有N个点N条边的连通图
形如
二、例题
力扣5970](https://leetcode-cn.com/problems/maximum-employees-to-be-invited-to-a-meeting/)
三、解题思路
由题目可知,判断一个员工是否能上桌,需要他喜欢的员工也要上桌,同时每个人身边最多只能做两个人,因此对于最后上桌的情况分为两种:
· 每个人,左边坐着喜欢自己的员工,右边做着自己喜欢的员工
· 有两个员工相互喜欢,可以补充喜欢这两个员工的人,补充的人最后一个人为没有人喜欢,
即左右两边其中一个坐着自己的喜欢的员工,另一个位置的人与自己无关。也满足题意
四、解题代码
拓扑排序 + 深度优先搜索 + 分类讨论
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| class Solution { public: int maximumInvitations(vector<int>& favorite) { int n = favorite.size(); vector<vector<int>>g(n),rg(n); vector<int>degree(n); for(int v = 0; v < n; ++v){ int w = favorite[v]; g[v].emplace_back(w); rg[w].emplace_back(v); ++degree[w]; } queue<int>Q; for(int i = 0; i < n; ++i){ if(degree[i] == 0) Q.push(i); } while(!Q.empty()){ int v = Q.front(); Q.pop(); for(int w : g[v]){ if (--degree[w] == 0) Q.push(w); } } vector<int>ring; vector<int>vis(n); function<void(int)> dfs = [&](int v){ vis[v] = true; ring.push_back(v); for(int w : g[v]){ if(!vis[w]) dfs(w); } }; int max_depth = 0; function<void(int,int,int)>rdfs = [&](int v ,int fa ,int depth){ max_depth = max(max_depth , depth); for(int w : rg[v]){ if (w != fa){ rdfs(w,v,depth+1); } } }; int max_ring_size = 0, sum_list_size = 0; for(int i = 0; i < n; ++i){ if (!vis[i] && degree[i] == 1){ ring.resize(0); dfs(i); int sz = ring.size(); if (sz == 2){ int v = ring[0], w = ring[1]; max_depth = 0; rdfs(v,w,1); sum_list_size += max_depth; max_depth = 0; rdfs(w,v,1); sum_list_size += max_depth; } else{ max_ring_size = max(max_ring_size , sz); } } } return max(max_ring_size,sum_list_size); } };
|
拓扑排序 + 深度优先搜索 + 动态规划 + 分类讨论
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| class Solution { public: int maximumInvitations(vector<int>& favorite) { int n = favorite.size(); int ans1 ,ans2 ; vector<int> vis(n), degree(n),dp(n,1); for(int i = 0; i < n; ++i)if (not vis[i]){ vector<int> w; int x = i; while(not vis[x]){ w.push_back(x); vis[x] = 1; x = favorite[x]; } for(int j = 0; j < w.size(); ++j){ if (w[j] == x){ ans1 = max((int)w.size() - j, ans1); } } } queue<int>Q; for(int i = 0; i < n; ++i) degree[favorite[i]]++; for(int i = 0; i < n; ++i) if (degree[i] == 0){ Q.push(i); } while(!Q.empty()){ int u = Q.front(); int v = favorite[u]; Q.pop(); dp[v] = max(dp[v],dp[u] + 1); if (not --degree[v]) Q.push(v); } for(int i = 0; i < n; ++i) if (favorite[favorite[i]]== i and favorite[i] > i){ ans2 += dp[i] + dp[favorite[i]]; } return max(ans1,ans2); } };
|