Submission #1336935

#TimeUsernameProblemLanguageResultExecution timeMemory
1336935liptonekKeys (IOI21_keys)C++20
37 / 100
3103 ms328776 KiB
#include <bits/stdc++.h>
using namespace std;

vector<int> find_reachable(vector<int> r, vector<int> u, vector<int> v, vector<int> c) 
{
    int n=r.size();
    int m=u.size();
    
    vector<vector<pair<int,int>>> adj(n);

	for(int i=0; i<m; i++) 
	{
        adj[u[i]].push_back({v[i],c[i]});
        adj[v[i]].push_back({u[i],c[i]});
    }

    vector<int> parent(n);

	iota(parent.begin(),parent.end(),0);
    
    auto find=[&](auto self, int i) -> int 
	{
        return(parent[i]==i) ? i :(parent[i]=self(self,parent[i]));
    };

    vector<set<int>> visited(n);
    vector<set<int>> held(n);   
    vector<map<int,vector<int>>> blocked(n);
    vector<queue<int>> q(n);      
    vector<int> status(n,0);      
    vector<bool> dead(n,false);   
    
    for(int i=0; i<n; i++) 
	{
        visited[i].insert(i);
        q[i].push(i);
    }

    auto merge=[&](int a, int b) 
	{
        a=find(find,a);
        b=find(find,b);
    
		if(a==b) 
		{
			return a;
		}

        if(visited[a].size()<visited[b].size()) 
		{
			swap(a,b);
		}
        
        parent[b]=a;
        
        for(int k : held[b]) 
		{
            if(held[a].find(k)==held[a].end()) 
			{
                held[a].insert(k);
            
				if(blocked[a].count(k)) 
				{
                    for(int target : blocked[a][k]) 
					{
                        if(visited[a].find(target)==visited[a].end()) 
						{
                            visited[a].insert(target);
                            q[a].push(target);
                        }
                    }

                    blocked[a].erase(k);
                }
            }
        }
        
        for(auto& it : blocked[b]) 
		{
            int k=it.first;
        
			if(held[a].count(k)) 
			{
                for(int target : it.second) 
				{
                    if(visited[a].find(target)==visited[a].end()) 
					{
                        visited[a].insert(target);
                        q[a].push(target);
                    }
                }
            } 
			else 
			{
                vector<int>& vec=blocked[a][k];
            
				vec.insert(vec.end(),it.second.begin(),it.second.end());
            }
        }
        
        while(!q[b].empty()) 
		{ 
			q[a].push(q[b].front()); 
			q[b].pop(); 
		}
        
		for(int room : visited[b]) 
		{
			visited[a].insert(room);
		}
        
        held[b].clear(); 
		blocked[b].clear(); 
		visited[b].clear();

		return a;
    };

    vector<int> final;
    
	for(int i=0; i<n; i++) 
	{
        int root=find(find,i);
    
		if(status[root]!=0) 
		{
			continue;
		}

        vector<int> path;
        
		path.push_back(root);
        
		status[root]=1;

        while(!path.empty()) 
		{
            int curr=path.back();
            int next=-1;

            while(!q[curr].empty()) 
			{
                int idx=q[curr].front();
                int target=find(find,idx);
                
                if(target!=curr) 
				{
                    next=target;
                
					break;
                }
                
                q[curr].pop();
                
                int type=r[idx];

				if(held[curr].find(type)==held[curr].end()) 
				{
                    held[curr].insert(type);
                
					if(blocked[curr].count(type)) 
					{
                        for(int neighbor : blocked[curr][type]) 
						{
                            if(visited[curr].find(neighbor)==visited[curr].end()) 
							{
                                visited[curr].insert(neighbor);
                                q[curr].push(neighbor);
                            }
                        }

                        blocked[curr].erase(type);
                    }
                }
                
                for(auto& edge : adj[idx]) 
				{
                    if(held[curr].count(edge.second)) 
					{
                        if(visited[curr].find(edge.first)==visited[curr].end()) 
						{
                            visited[curr].insert(edge.first);
                            q[curr].push(edge.first);
                        }
                    } 
					else 
					{
                        blocked[curr][edge.second].push_back(edge.first);
                    }
                }
            }

            if(next==-1) 
			{
                status[curr]=2;
            
				final.push_back(curr);
                path.pop_back();
            } 
			else if(status[next]==1) 
			{
                int merged=curr;
            
				while(path.back()!=next) 
				{
                    path.pop_back();
                
					merged=merge(merged,path.back());
                }
                
				path.pop_back(); 
				path.push_back(merged);
            } 
			else if(status[next]==2) 
			{
                for(int node : path) 
				{ 
					status[node]=2; 
					dead[node]=true; 
				}
                
				path.clear();
            } 
			else 
			{
                status[next]=1;

				path.push_back(next);
            }
        }
    }

    int np=n+1;

	for(int sink : final) 
	{
        if(!dead[sink]) 
		{
			np=min(np,(int)visited[sink].size());
		}
    }

    vector<int> ans(n,0);
    
	for(int sink : final) 
	{
        if(!dead[sink] &&(int)visited[sink].size()==np) 
		{
            for(int room : visited[sink]) 
			{
				ans[room]=1;
			}
        }
    }

    return ans;
}
#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...