社区讨论
求调
学术版参与者 3已保存回复 2
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @m5t6jpb0
- 此快照首次捕获于
- 2025/01/12 13:33 去年
- 此快照最后确认于
- 2025/11/04 11:43 4 个月前
P4606MLE 0pts求调,能过样例,把树剖求LCA改成倍增求LCA就AC了,但不知道我的树剖求LCA哪里写错了
CPP#include<bits/stdc++.h>
using namespace std;
int n,m,k,t,cnt,dfn[200005],low[100005],st[100005],top,cnt2,x,y,ans,s[200005],ss[100005],dep[200005],f[200005],son[200005],tp[200005],dis[200005];
vector<int> v1[100005],v2[200005];
void tarjan(int u) {
low[u]=dfn[u]=++cnt;
st[++top]=u;
for (auto v:v1[u]) {
if (!dfn[v]) {
tarjan(v);
low[u]=min(low[u], low[v]);
if (low[v]==dfn[u]) {
++cnt2;
int x=0;
while(x!=v){
x=st[top];
v2[cnt2].push_back(x);
v2[x].push_back(cnt2);
top--;
}
v2[cnt2].push_back(u);
v2[u].push_back(cnt2);
}
}
else low[u]=min(low[u],dfn[v]);
}
}
void dfs1(int u,int fa){
f[u]=fa;
dep[u]=dep[fa]+1;
dis[u]=dis[fa];
dfn[u]=++cnt;
if(u<=n) dis[u]++;
s[u]=1;
int mson=-1;
for(auto v:v2[u]){
if(v==fa) continue;
dfs1(v,u);
s[u]+=s[v];
if(s[v]>mson){
mson=s[v];
son[u]=v;
}
}
}
void dfs2(int u,int fa){
tp[u]=fa;
if(son[u]==0) return ;
dfs2(son[u],fa);
for(auto v:v2[u]){
if(v==f[u]||v==son[u]) continue;
dfs2(v,v);
}
}
int lca(int x,int y){
while(tp[x]!=tp[y]){
if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
x=f[tp[x]];
}
if(dep[x]>dep[y]) swap(x,y);
return x;
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) {v1[i].clear();dfn[i]=low[i]=0;}
for(int i=1;i<=2*n;i++){
v2[i].clear();
}
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
v1[x].push_back(y);
v1[y].push_back(x);
}
cnt=0;
top=0;
cnt2=n;
tarjan(1);
top--;
cnt=0;
dfs1(1,0);
dfs2(1,1);
scanf("%d",&k);
for(int i=1;i<=k;i++){
ans=0;
scanf("%d",&x);
for(int j=1;j<=x;j++){
scanf("%d",&ss[j]);
}
sort(ss+1,ss+x+1,[](int a,int b) { return dfn[a]<dfn[b];});
for (int j=1;j<=x;j++){
int u=ss[j],v=ss[j%x+1];
ans+=dis[u]+dis[v]-2*dis[lca(u,v)];
//cout<<u<<" "<<dis[u]<<" "<<dis[v]<<" ";
}
if (lca(ss[1], ss[x])<=n) ans+=2;
ans-=x*2;
ans/=2;
printf("%d\n",ans);
}
}
return 0;
}
回复
共 2 条回复,欢迎继续交流。
正在加载回复...