zoukankan      html  css  js  c++  java
  • CF613D Kingdom and its Cities

    虚树+DP

    DP:(f[u]) 表示 (u) 的答案,(sz[u]) 表示 (u) 向上传递的贡献(在一开始是用来记录子树中需要截断多少个关键点)。当前点是关键点,则全部截断子树中的点并令 (sz[u]=1) ,向上传递;当前点不是关键点,若底下有多个点,则把当前点去掉,若底下只有一个点,向上传递。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #define R register int
    using namespace std;
    namespace Luitaryi {
    inline int g() { R x=0,f=1;
      register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
      do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
    } const int N=100010;
    int n,m,k;
    int vr[N<<1],nxt[N<<1],fir[N],cnt,num,d[N],pre[N],top[N],dfn[N],sz[N],son[N];
    int stk[N],h[N],f[N],ans[N]; bool vis[N];
    inline void add(int u,int v) 
      {vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;}
    inline void dfs(int u) {
      dfn[u]=++num,sz[u]=1;
      for(R i=fir[u];i;i=nxt[i]) {
        R v=vr[i];
        if(dfn[v]) continue;
        d[v]=d[u]+1,pre[v]=u;
        dfs(v);
        sz[u]+=sz[v];
        if(sz[son[u]]<sz[v]) son[u]=v;
      }
    }
    inline void dfs2(int u,int tp) {
      top[u]=tp;
      if(son[u]) dfs2(son[u],tp);
      for(R i=fir[u];i;i=nxt[i]) {
        R v=vr[i];
        if(top[v]) continue;
        dfs2(v,v);
      }
    }
    inline int lca(int u,int v) {
      while(top[u]!=top[v]) {
        if(d[top[u]]<d[top[v]]) swap(u,v);
        u=pre[top[u]];
      } return d[u]<d[v]?u:v;
    }
    inline bool cmp(const int& a,const int& b) 
      {return dfn[a]<dfn[b];}
    inline void dp(int u) {
      f[u]=sz[u]=0;
      for(R i=fir[u];i;i=nxt[i]) {
        R v=vr[i];
        dp(v);
        f[u]+=f[v];
        sz[u]+=sz[v];
      }
      if(vis[u]) f[u]+=sz[u],sz[u]=1;
      else if(sz[u]>1) sz[u]=0,++f[u];   
    }
    inline void main() {
      n=g();
      for(R i=1,u,v;i<n;++i) 
        u=g(),v=g(),add(u,v),add(v,u);
      d[1]=1,dfs(1),dfs2(1,1);
      memset(fir,0,sizeof fir);
      m=g(); while(m--) {
        k=g(); 
        for(R i=1;i<=k;++i) vis[h[i]=g()]=true;
        for(R i=1;i<=k;++i) if(vis[pre[h[i]]]) 
          {puts("-1"); goto end;}
        sort(h+1,h+k+1,cmp);
        fir[1]=cnt=0; R top;
        stk[top=1]=1;
        for(R i=1+(h[1]==1),l;i<=k;++i) {
          l=lca(h[i],stk[top]);
          if(l!=stk[top]) {
            while(dfn[l]<dfn[stk[top-1]]) 
              add(stk[top-1],stk[top]),--top;
            if(dfn[l]>dfn[stk[top-1]]) 
              fir[l]=0,
              add(l,stk[top]),stk[top]=l;
            else
              add(l,stk[top]),--top;
          }
          fir[h[i]]=0,stk[++top]=h[i];
        }
        for(R i=1;i<top;++i) 
          add(stk[i],stk[i+1]);
        dp(1);
        printf("%d
    ",f[1]);
        end:for(R i=1;i<=k;++i) vis[h[i]]=0;
      }
    }
    } signed main() {Luitaryi::main(); return 0;}
    

    2020.01.18

  • 相关阅读:
    学习php 韩顺平 数据类型 三元运算,字符串运算类型运算
    学习php 韩顺平
    贪小便宜吃大亏关于汇泽平板和智能手表
    学习spring的第三天
    学习spring的第二天
    学习spring的第一天
    mybatis批量添加和删除
    关于mybatis的<selectKey>中的keyColumn
    mybatis+maven+父子多模块进行crud以及动态条件查询
    mybatis的插入数据后的主键获取
  • 原文地址:https://www.cnblogs.com/Jackpei/p/12208329.html
Copyright © 2011-2022 走看看