爆零哩
一下给出主体部分
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();
}