Submission #1257022

#TimeUsernameProblemLanguageResultExecution timeMemory
1257022noyancanturkCapital City (JOI20_capital_city)C++20
11 / 100
3095 ms40488 KiB
#include<bits/stdc++.h>
using namespace std;

#define pb push_back

using pii=pair<int,int>;

const int lim=2e5+100;

vector<int>v[lim];
int a[lim];
int ans;

int tin[lim],tout[lim],tt=1;

int parent[lim];

void dfs(int node,int par){
  parent[node]=par;
  tin[node]=tt++;
  for(int j:v[node]){
    if(j==par)continue;
    dfs(j,node);
  }
  tout[node]=tt-1;
}

struct comp{
  bool operator()(int x,int y)const {
    return tin[x]<tin[y];
  }
};

set<int,comp>st;

int vis[lim];

int tot;

int sz[lim];

int sbs(int node,int par){
  sz[node]=1;
  for(int j:v[node]){
    if(j==par||vis[j])continue;
    sz[node]+=sbs(j,node);
  }
  return sz[node];
}

int findcen(int node,int par){
  for(int j:v[node]){
    if(j!=par&&!vis[j]&&2*sz[j]>tot)return findcen(j,node);
  }
  return node;
}

unordered_map<int,int>cnt;
unordered_set<int>taken;
vector<int>guys[lim];

void calccnt(int node,int par){
  cnt[a[node]]++;
  for(int j:v[node]){
    if(j==par||vis[j])continue;
    calccnt(j,node);
  }
}

void decomp(int node){
  tot=sbs(node,0);
  node=findcen(node,0);
  cnt.clear();
  calccnt(node,0);
  if(cnt[a[node]]==guys[a[node]].size()){
    taken.clear();
    st.clear();
    queue<int>need;
    unordered_set<int>cols;
    cols.insert(a[node]);
    for(int j:guys[a[node]]){
      need.push(j);
    }
    int head=need.front();
    need.pop();
    taken.insert(head);
    // cerr<<"head is "<<head<<'\n';
    // cerr<<"can get ";
    for(int j:v[head]){
      if(j!=parent[head]&&!vis[j]&&!taken.count(j)){
        // cerr<<j<<' ';
        st.insert(j);
      }
    }
    // cerr<<'\n';
    int cant=0;
    while(need.size()&&!cant){
      int totake=need.front();
      need.pop();
      while(!taken.count(totake)&&!cant){
        if(!st.size()||tin[totake]<tin[*st.begin()]||tin[totake]>tout[*st.rbegin()]){
          if(!parent[head]||vis[parent[head]]){
            cant=1;
            break;
          }else{
            head=parent[head];
            if(cnt[a[head]]!=guys[a[head]].size()){
              cant=1;
              break;
            }
            if(!cols.count(a[head])){
              cols.insert(a[head]);
              for(int j:guys[a[head]]){
                need.push(j);
              }
            }
            // cerr<<"took old parent "<<head<<'\n';
            taken.insert(head);
            for(int j:v[head]){
              if(j!=parent[head]&&!vis[j]&&!taken.count(j)){
                st.insert(j);
              }
            }
          }
        }else{
          auto p=prev(st.upper_bound(totake));
          int guy=*p;
          if(cnt[a[guy]]!=guys[a[guy]].size()){
            cant=1;
            break;
          }
          if(!cols.count(a[guy])){
            cols.insert(a[guy]);
            for(int j:guys[a[guy]]){
              need.push(j);
            }
          }
          // cerr<<"took old fashion "<<guy<<'\n';
          taken.insert(guy);
          for(int j:v[guy]){
            if(j!=parent[guy]&&!vis[j]&&!taken.count(j)){
              st.insert(j);
            }
          }
        }
      }
    }
    if(!cant){
      // cerr<<"found one\n";
      // cerr<<"cols :: ";
      // for(int i:cols)cerr<<i<<' ';
      // cerr<<'\n';
      // cerr<<"taken :: ";
      // for(int i:taken)cerr<<i<<' ';
      // cerr<<'\n';
      ans=min<int>(ans,cols.size()-1);
    }
  }
  vis[node]=1;
  for(int j:v[node]){
    if(!vis[j]){
      decomp(j);
    }
  }
}

int main(){
  int n,__;
  cin>>n>>__;
  for(int i=0;i<n-1;i++){
    int x,y;
    cin>>x>>y;
    v[x].pb(y);
    v[y].pb(x); 
  }
  for(int i=1;i<=n;i++){
    cin>>a[i];
    guys[a[i]].pb(i);
  }
  ans=n;
  dfs(1,0);
  decomp(1);
  cout<<ans<<'\n';
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...