蒟蒻刚学圆方树0ms
查看原帖
蒟蒻刚学圆方树0ms
85994
嘉年华楼主2022/4/16 16:54

爆零哩

一下给出主体部分

int n,m,q;
int tot;//圆方树节点数 
vector<int> g[maxn],t[maxn<<1];//g是原图,t是圆方树的图 
int dfn[maxn],low[maxn],dfn_cnt;//tarjan
int sum[maxn<<1];//节点到根的路径数值和 
int trdfn[maxn<<1],trcnt;//节点在圆方树上的dfs序 
int top[maxn<<1];
int son[maxn<<1],siz[maxn<<1];//树链剖分求lca 
int dep[maxn<<1];//节点深度 
int acs[maxn<<1];//在圆方树上的父亲 
int rt;

inline void cls()
{
	for(int i=1;i<=tot;++i) t[i].clear();
	for(int i=1;i<=n;++i)
		g[i].clear(),
		low[i]=dfn[i]=0;
	memset(sum,0,sizeof(int)*tot);
	memset(trdfn,0,sizeof(int)*tot);
	memset(top,0,sizeof(int)*tot);
	memset(son,0,sizeof(int)*tot);
	memset(siz,0,sizeof(int)*tot);
	memset(dep,0,sizeof(int)*tot);
	memset(acs,0,sizeof(int)*tot);
}//清空 

inline void link(int a,int b,vector<int>* h)
{
	(h+a)->emplace_back(b);
	(h+b)->emplace_back(a);
}//连边 

inline void tarjan(int u)
{
static stack<int> stk;
	debug_out(u);
	low[u]=dfn[u]=++dfn_cnt;
	stk.push(u);
	for(int v:g[u])
		if(!dfn[v])
		{
			tarjan(v);
			low[u] = min( low[u] , low[v] );
			if( dfn[u] == low[v] )
			{
				++tot;
				for(;stk.top()!=u;stk.pop())
					link(stk.top(),tot,t);
				link(u,tot,t);
			}
		}
		else low[u] = min(low[u],dfn[v]);
//	while(!stk.empty()) stk.pop();
}//构建圆方树 

#define is_circle(u) (u<=n)
//是否是圆方树上的节点 
inline void dfs1(int u,int fa=0)
{
	trdfn[u] = ++trcnt;
	acs[u] = fa ,
	dep[u] = dep[fa] + (siz[u]=1) ,
	sum[u] = sum[fa] + (is_circle(u)?1:0) ;
	for(int v : t[u])
		if(v != fa)
			dfs1(v,u),
			siz[u] += v;
}
inline void dfs2(int u,int tp)
{
	top[u] = tp;
	int mx(0),mxid(0);
	for(int v:t[u])
		if(siz[v] > mx && !son[v])
			mx = siz[v],
			mxid = v;
	son[u] = mxid;
	for(int v:t[u])
		if(!son[v])
		{
			if(v == son[u])
				dfs2(v,tp);
			else
				dfs2(v,v);
		}
}//树链剖分 

inline int lca(int u,int v)
{
	while(top[u] != top[v])
	{
		if(dep[top[u]] > dep[top[v]]) swap(u,v);
		v = acs[top[v]];
	}
	return dep[u]<dep[v]?u:v;
} inline int line_sum(int u,int v) {return sum[u] - (sum[lca(u,v)]<<1) + sum[v];}
//lca

inline void read_graph()
{
	read_(n,m);
	for(int i(1),u,v ; i <= m ; ++i)
		read_(u,v),
		link(u,v,g);
	tot = n;
	for(int i(1) ; i <= n ; ++i)
		if(!dfn[i])
			tarjan(i);
	rt = 1 , trcnt = 0 ;
	dfs1(rt);
	dfs2(rt,rt);
} inline bool cmp(int a,int b) {return trdfn[a] > trdfn[b];}
//读入 

inline void solve()
{
	read_graph();
	read_(q);
	int s,as;
static vector<int> tmp;
	while(q--)
	{
		as=0;
		read_(s);
		for(int x,i(1); i <= s ; ++i)
			read_(x),
			tmp.emplace_back(x);
		sort(tmp.begin(),tmp.end(),cmp);//按dfs序排序 
		tmp.emplace_back(tmp[0]);
		for(unsigned i(1);i<tmp.size();++i)
			as+=line_sum(tmp[i],tmp[i-1]);
		as= (as>>1) - s ;
		as += is_circle(lca(tmp[s-1],tmp[0]));
		write_(as,'\n');
		tmp.clear();
	}
	cls();
}
2022/4/16 16:54
加载中...