Submission #339248

#TimeUsernameProblemLanguageResultExecution timeMemory
339248KWang31Mergers (JOI19_mergers)Java
56 / 100
3070 ms50412 KiB
import java.io.*; import java.util.*;
public class mergers{
  static class FastReader 
    { 
        BufferedReader br; 
        StringTokenizer st; 
  
        public FastReader() 
        { 
            br = new BufferedReader(new
                     InputStreamReader(System.in)); 
        } 
  
        String next() 
        { 
            while (st == null || !st.hasMoreElements()) 
            { 
                try
                { 
                    st = new StringTokenizer(br.readLine()); 
                } 
                catch (IOException  e) 
                { 
                    e.printStackTrace(); 
                } 
            } 
            return st.nextToken(); 
        } 
  
        int nextInt() 
        { 
            return Integer.parseInt(next()); 
        } 
  
        
    } 
    public static class Pair implements Comparable<Pair>{
        int vtx; int val;
        public Pair(int a, int b){
            this.vtx=a; this.val=b;
        }
        public int compareTo(Pair other){
            if(this.val<other.val)return -1;
            if(this.val>other.val)return 1;
            if(this.vtx<other.vtx)return -1;
            return 1;
        }
    }
    static int MOD=998244353;
    static int[] rk, p,siz;
    static int[] par,dep;
    public static void main(String[] args){
        FastReader br=new FastReader();
        int N=br.nextInt(); int M=br.nextInt();
        ArrayList<Integer> states[]=new ArrayList[M]; for(int i=0;i<M;i++){states[i]=new ArrayList<>();}
        ArrayList<Integer> adj[]=new ArrayList[N]; for(int i=0;i<N;i++){adj[i]=new ArrayList<>();}
        int a,b;
        for (int i = 0; i < N-1; i++) {
            a=br.nextInt()-1; b=br.nextInt()-1; adj[a].add(b); adj[b].add(a);
        }
        for (int i = 0; i < N; i++) {
            a=br.nextInt()-1; states[a].add(i);
        }
        par=new int[N]; dep=new int[N]; dfs(adj,-1,0);
        
        int[] skip=new int[N];//Skipping: avoiding repeated merging
        for (int i = 0; i < N; i++) {
            skip[i]=i;
        }
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < states[i].size()-1; j++) {
                a=states[i].get(j); b=states[i].get(j+1);
                
                while(a!=b){
                    if(dep[a]>=dep[b]){
                        skip[a]=find(par[a],skip); a=par[a]; 
                    }else{
                        skip[b]=find(par[b],skip); b=par[b]; 
                    }
                }
                //For each a, we have merged a with its 1st, .., kth ancestor.
                //They belong to the same state
            }
        }
        //In the end, all vertices of the same state have the same skip
        //Therefore, after merging, if two vertices don't have some skip, they are not in the same state
        int[] deg=new int[N];
        
        for (int i = 0; i < N; i++) {
            a=find(i,skip);
            for (int j : adj[i]) {
                if(a!=find(j,skip)){
                    //Notice in the compressed form, there is only one leader for each state, namely j
                    //If i is adjacent to two vertices with same find, i must have that find too
                    deg[a]++;
                }
            }
        }
        //System.out.println(Arrays.toString(deg));
        int ans=0;
        for (int i = 0; i < N; i++) {
            if(deg[i]==1)ans++;
        }
        System.out.println((ans+1)/2);
        //If a state is a leaf, there exist exactly one 
    }
    
    public static int find(int x, int[] p){
        if(p[x]==x)return x;
        p[x]=find(p[x],p); return p[x];
    }
    
    public static void merge(int a, int b) {
        if(rk[a]<rk[b]) {
            p[a]=b; siz[b]+=siz[a];
        }else if(rk[a]==rk[b]) {
            p[a]=b; rk[b]++;siz[b]+=siz[a];
        }else {
            p[b]=a; siz[a]+=siz[b];
        }
    }
    public static void dfs(ArrayList<Integer>[] adj, int p, int v){
        for (int c : adj[v]) {
            if(c==p)continue;
            dep[c]=dep[v]+1; par[c]=v; dfs(adj,v,c);
        }
    }
}
//Debugging:
//Are you sure your algorithm is correct?
//Bounds: long
//Special cases: n=0,1?
//Make sure you remove your debugging code before you submit!

Compilation message (stderr)

Note: mergers.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...