1 条题解

  • 0
    @ 2024-11-10 20:53:50

    对于原图所有入度为00的结点,从结点00到该结点连边。

    定义结点uufafa结点fa[u]fa[u]满足如下条件:存在fa[u]fa[u]uu的至少一条路径,且不存在结点vv,使得删去vvuu点不可不可到达。连接所有fa[u]fa[u]uu,可以构成一棵树。由于原图有向无环,fa[u]fa[u]只与uu的前驱有关。在连接所有fa[u]fa[u]uu构成的树上,原图中uu所有前驱在树上的lcalca即为fa[u]fa[u]

    #include<bits/stdc++.h>
    using namespace std;
    using PII=std::pair<int,int>;
    using i64=long long;
    struct Tree{
    	int n;
    	std::vector<int> stk,tpn;
    	std::vector<std::vector<int>> g1,g2,tr;
    	std::vector<std::array<int,17>> fth;
    	std::vector<int> in,dep,fa,siz;
    	Tree(int num){
    		init(num);
    	}
    	void init(int num){
    		this->n=num-1;
    		stk.clear();
    		tpn.clear();
    		g1.assign(num,{});
    		g2.assign(num,{});
    		tr.assign(num,{});
    		fth.assign(num,std::array<int,17>());
    		in.assign(num,0);
    		dep.assign(num,0);
    		fa.assign(num,-1);
    		siz.assign(n+1,0);
    	}
    	void add(int u,int v){
    		g1[u].push_back(v);
    		in[v]++;
    		g2[v].push_back(u);
    	}
    	void topo(){
    		stk.push_back(0);
    		for(int i=1;i<=n;i++){
    			if(in[i]!=0)continue;
    			g1[0].push_back(i);
    			g2[i].push_back(0);
    			in[i]++;
    		}
    		while(stk.size()){
    			auto u=stk.back();;
    			stk.pop_back();
    			tpn.push_back(u);
    			for(auto v:g1[u]){
    				in[v]--;
    				if(in[v]==0)stk.push_back(v);
    			}
    		}
    	}
    	int lca(int u,int v){
    		if(dep[u]<dep[v])std::swap(u,v);
    		for(int i=16;i>=0;i--){
    			if(dep[fth[u][i]]>=dep[v]){
    				u=fth[u][i];
    			}
    		}
    		if(u==v)return u;
    		for(int i=16;i>=0;i--){
    			if(fth[u][i]!=fth[v][i]){
    				u=fth[u][i];
    				v=fth[v][i];
    			}
    		}
    		return fth[u][0];
    	}
    	void build(){
    		topo();
    		for(int i=1;i<=n;i++){
    			int u=tpn[i],v=g2[u][0];
    			for(int j=1;j<g2[u].size();j++){
    				v=lca(v,g2[u][j]);
    			}
    			tr[v].push_back(u);
    			fa[u]=v;
    			dep[u]=dep[v]+1;
    			fth[u][0]=v;
    			for(int i=1;i<=16;i++){
    				fth[u][i]=fth[fth[u][i-1]][i-1];
    			}
    		}		
    	}
    	void dfs(int u=0){
    		siz[u]=1;
    		for(auto v:tr[u]){
    			dfs(v);
    			siz[u]+=siz[v];
    		}
    	}
    };
    void solve(){
    	int n;std::cin>>n;
    	Tree tr(n+1);
    	for(int i=1;i<=n;i++){
    		int x;std::cin>>x;
    		while(x--){
    			int y;std::cin>>y;
    			tr.add(y,i);
    		}		
    	}
    	tr.build();
    	tr.dfs();
    	for(int i=1;i<=n;i++){
    		std::cout<<tr.siz[i]<<'\n';
    	}	
    }
    
    signed main(){
    	std::cin.tie(nullptr);
    	std::ios::sync_with_stdio(false);
    	std::cout<<std::fixed<<std::setprecision(10);
    	solve();
    	return 0;
    }
    
    
    • 1

    信息

    ID
    258
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    (无)
    递交数
    10
    已通过
    2
    上传者