1 条题解

  • 0
    @ 2026-5-7 11:43:56

    题面

    设某个副部长要连的点集为 hh,要求这个副部长所选的边。

    我们会发现,如果将 hh 中所有元素按 dfs\text{dfs} 序排列,然后依次相连,并且第一个元素和最后一个元素相连,就会形成一个环。

    而环上的边就是副部长要选的,并且都会被重复计算两次。

    为什么按 dfs\text{dfs} 序排序?因为按这样的话,如果到某个 hih_i 之前的所有点都在同一条链上,而 hi+1h_{i+1} 在另一条链上,那 hih_i 一定是一条链的结尾,hi+1h_{i+1} 一定是另一条链的开头。

    那么所有链就会头尾相连,必定形成一个每条边都重复两次的环。

    然后用树上差分和倍增维护一下就行了。

    代码:

    #include<bits/stdc++.h>
    #define N 100005
    using namespace std;
    int n,m,K,s,u,v,h[N],d[N];
    int head[N],nxt[N<<1],to[N<<1],cnt;
    inline void add(int x,int y){
        to[++cnt]=y;
        nxt[cnt]=head[x];
        head[x]=cnt;
    }
    int fa[N][21],dep[N],id[N],tot;
    void dfs(int k){
        for(int i(1);i<=20;++i)
            fa[k][i]=fa[fa[k][i-1]][i-1];
        id[k]=++tot;
        for(int i(head[k]);i;i=nxt[i])
            if(!id[to[i]]){
                fa[to[i]][0]=k;
                dep[to[i]]=dep[k]+1;
                dfs(to[i]);
            }
    }
    inline int LCA(int x,int y){
        if(dep[x]<dep[y]) swap(x,y);
        for(int i(20);~i;--i){
            if(dep[fa[x][i]]>=dep[y])
                x=fa[x][i];
            if(x==y) return x;
        }
        for(int i(20);~i;--i)
            if(fa[x][i]^fa[y][i]){
                x=fa[x][i];
                y=fa[y][i];
            }
        return fa[x][0];
    }
    inline bool cmp(const int&a,const int&b){
        return id[a]<id[b];
    }
    vector <int> vec;
    void CCF(int k,int f){
        for(int i(head[k]);i;i=nxt[i])
            if(to[i]^f){
                CCF(to[i],k);
                d[k]+=d[to[i]];
                if(d[to[i]]>=2*K) vec.push_back(i+1>>1);
            }
    }
    int main(){
        scanf("%d%d%d",&n,&m,&K);
        for(int i(1);i<n;++i){
            scanf("%d%d",&u,&v);
            add(u,v);add(v,u);
        }
        dep[1]=1;dfs(1);
        for(int i(1);i<=m;++i){
            scanf("%d",&s);
            for(int j(1);j<=s;++j) scanf("%d",&h[j]);
            sort(h+1,h+1+s,cmp);
            for(int j(1);j<s;++j){
                ++d[h[j]];
                ++d[h[j+1]];
                d[LCA(h[j],h[j+1])]-=2;
            }	
            ++d[h[1]];
            ++d[h[s]];
            d[LCA(h[1],h[s])]-=2;
        }
        CCF(1,0);printf("%d\n",vec.size());sort(vec.begin(),vec.end());
        for(int i(0);i<vec.size();++i) printf("%d ",vec[i]);puts("");
        return 0;
    }
    
    • 1

    信息

    ID
    10559
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者