题意
在树上存在n个点,每个点为两种状态之一,两种状态的点之间无法相互抵达,求树上最大的可联通子树,并按递增顺序输出所有节点,若有多棵子树最大,将所有子树节点均排序输出。
题解
对树进行dfs,每次求一颗子树大小,并将其所有节点标记,遍历过程记录子树个数与其所有节点,最后找到最大联通子树将所有最大子树的节点放到数组中排序输出
code
#include <bits/stdc++.h> #define reg register #define ll long long #define ull unsigned long long #define pii pair<int,int> #define inf 0x3f3f3f3f #define eps 1e-8 #define pi acos(-1.0) #define e exp(1.0) #define ios ios::sync_with_stdio(false) #define rep(i,l,r) for(int i=(l);i<(r);i++) using namespace std; const int maxn = 2e5 + 10; const int mod = 1e9 + 7; int val[maxn]; vector<int> son[maxn]; vector<int> s[maxn]; //所有联通子树集合 bool vis[maxn]; void dfs(int x,int p) { s[p].push_back(x); for(int i = 0;i < son[x].size();++i){ int to = son[x][i]; if(!vis[to] && val[to] == val[x]){ vis[to] = 1; dfs(to,p); } } } int main() { ios; int n; cin>>n; for(int i = 1;i <= n;++i) cin>>val[i]; for(int i = 0;i < n-1;++i){ int u,v; cin>>u>>v; son[u].push_back(v); son[v].push_back(u); } int cnt = 0; for(int i = 1;i <= n;++i){ if(!vis[i]){ vis[i] = 1; dfs(i,cnt); cnt++; } } int mx = 0; vector<int> m; //可选下标集合 int sum = 0; for(int i = 0;i < cnt;++i){ if(s[i].size() > mx){ m.clear(); m.push_back(i); mx = s[i].size(); sum = mx; } else if(s[i].size() == mx) m.push_back(i),sum += mx; } printf("%d\n",sum); vector<int> all; for(int i = 0;i < m.size();++i){ for(int j = 0;j < s[m[i]].size();++j){ all.push_back(s[m[i]][j]); } } sort(all.begin(),all.end()); for(int i = 0;i < all.size()-1;++i) printf("%d ",all[i]); printf("%d\n",all.back()); return 0; }