返回顶部

牛客小白月赛28 J.树上行走 (并查集,dfs)

  • 题意:有\(n\)个点,\(n-1\)条边,每个点的类型是\(0\)\(1\),现在让你选一个点,然后所有与该点类型不同的点直接消失,问选哪些点之后,该点所在的联通块最大.

  • 题解:

    1. 因为选完之后两个类型不同的点之间的边会消失,所以我们可以直接维护一个并查集,每个集合中存的是相同类型的点的连通数量,维护最大值即可.
    2. 这题也可以用dfs来写,我们可以直接在dfs求连通块的同时用动态数组记录这个连通块中每个点的下标,然后去维护数组长度的最大值,模拟一下,具体细节看代码吧.
  • 代码:

    1. dsu:

      int n;
      int a[N];
      int cnt[N];
      int p[N];
      vector<int> ans;
       
      int find(int x){
          if(p[x]!=x) p[x]=find(p[x]);
          return p[x];
      }
       
      int main() {
          //ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
          n=read();
          for(int i=1;i<=n;++i){
              a[i]=read();
              cnt[i]=1;
              p[i]=i;
          }
       
          for(int i=1;i<n;++i){
              int u,v;
              u=read(),v=read();
              if(a[u]==a[v]){
                  int fu=find(u);
                  int fv=find(v);
                  if(fu!=fv){
                      p[fu]=fv;
                      cnt[fv]+=cnt[fu];
                  }
              }
          }
       
          int res=0;
          for(int i=1;i<=n;++i){
              int fa=find(i);
              res=max(res,cnt[fa]);
          }
          for(int i=1;i<=n;++i){
              if(cnt[find(i)]==res) ans.pb(i);
          }
          printf("%d\n",ans.size());
          for(auto w:ans) printf("%d ",w);
       
          return 0;
      }
      
    2. dfs:

      int n;
      int val[N];
      vector<int> v[N],s[N];
      vector<int> all,res;
      int cnt;
      bool st[N];
       
      void dfs(int u,int t){
          s[t].pb(u);
          for(auto w:v[u]){
              if(!st[w] && val[w]==val[u]){
                  st[w]=true;
                  dfs(w,t);
              }
          }
      }
       
      int main() {
          ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
          cin>>n;
          for(int i=1;i<=n;++i){
              cin>>val[i];
          }
          for(int i=1;i<n;++i){
              int a,b;
              cin>>a>>b;
              v[a].pb(b);
              v[b].pb(a);
          }
       
          for(int i=1;i<=n;++i){
              if(!st[i]){
                  st[i]=true;
                  dfs(i,cnt);
                  cnt++;
              }
          }
          int mx=0;
          int cur=0;
          for(int i=0;i<cnt;++i){
              if(s[i].size()>mx){
                  all.clear();
                  mx=s[i].size();
                  cur=mx;
                  all.pb(i);
              }
              else if(s[i].size()==mx){
                  all.pb(i);
                  cur+=mx;
              }
          }
          for(auto w:all){
              for(int j=0;j<s[w].size();++j){
                  res.pb(s[w][j]);
              }
          }
          sort(res.begin(),res.end());
          cout<<cur<<endl;
          for(auto w:res) cout<<w<<" ";
       
          return 0;
      }
      
posted @ 2020-09-24 20:41  _Kolibri  阅读(79)  评论(0)    收藏  举报