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

    最近调题都好艰辛啊……(请忽略弱者的一句感叹)

    虚树,为关键点及其(lca)构成的树,在这棵树上跑(dp)有时可以降低复杂度。

    若我有(m)个关键点,以下给出虚树建树模板:

    st[++top]=1;beg[1]=0;
    for(int i=1;i<=m;i++){
          if(a[i]==1)continue;
          int anc=lca(a[i],st[top]);
          if(anc!=st[top]){
                while(top>1&&dep[st[top-1]]>dep[anc])
                      add(st[top-1],st[top]),top--;
                if(st[top-1]]!=anc)beg[anc]=0,add(anc,st[top]),st[top]=anc;
                else add(anc,st[top--]);
          }
          beg[a[i]]=0;st[++top]=a[i];
    }
    for(int i=1;i<top;i++)
          add(st[top],st[top+1]);
    

    然后在虚树上(dp)

    若此点为关键点,则任意子关键点都有1的贡献(必须切断中间的一个点)。

    否则,若有多于一个关键子节点,则产生1的贡献(必须切断此点)。

    代码如下,仅供参考:

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    	return x*f;
    }
    const int maxn=1e5+10;
    int n,m,cnt,ans,a[maxn],val[maxn];
    int beg[maxn],nex[maxn<<1],to[maxn<<1],e;
    inline void add(int x,int y){
    	e++;nex[e]=beg[x];
    	beg[x]=e;to[e]=y;
    }
    int dep[maxn],dfn[maxn],f[maxn][20];
    inline void dfs(int x,int fa){
    	dep[x]=dep[fa]+1;
    	f[x][0]=fa;dfn[x]=++cnt;
    	for(int i=1;i<=19;i++)
    		f[x][i]=f[f[x][i-1]][i-1];
    	for(int i=beg[x];i;i=nex[i])
    		if(to[i]!=fa)dfs(to[i],x);
    }
    int st[maxn],top;
    inline int cmp(int x,int y){return dfn[x]<dfn[y];}
    inline int lca(int x,int y){
    	if(dep[x]<dep[y])swap(x,y);
    	for(int i=19;i>=0;i--)
    		if(dep[f[x][i]]>=dep[y])x=f[x][i];
    	if(x==y)return x;
    	for(int i=19;i>=0;i--)
    		if(f[x][i]!=f[y][i]){
    			x=f[x][i];
    			y=f[y][i];
    		}
    	return f[x][0];
    }
    int siz[maxn],dp[maxn];
    inline void solve(int x){
    	siz[x]=dp[x]=0;
    	for(int i=beg[x];i;i=nex[i]){
    		int t=to[i];
    		solve(t);
    		siz[x]+=siz[t];
    		dp[x]+=dp[t];
    	}
    	if(val[x])dp[x]+=siz[x],siz[x]=1;
    	else if(siz[x]>1)siz[x]=0,dp[x]++;
    }
    int main(){
    	n=read();
    	int x,y;
    	for(int i=1;i<n;i++){
    		x=read(),y=read();
    		add(x,y),add(y,x);
    	}
    	dfs(1,0);
    	memset(beg,0,sizeof(beg));e=0;
    	m=read();
    	for(int i=1;i<=m;i++){
    		cnt=read();top=e=0;
    		for(int j=1;j<=cnt;j++)
    			a[j]=read(),val[a[j]]=1;
    		int flag=0;
    		for(int j=1;j<=cnt;j++)
    			if(val[f[a[j]][0]])flag=1;
    		if(flag){
    			for(int j=1;j<=cnt;j++)
    				val[a[j]]=0;
    			puts("-1");
    			continue;
    		}
    		sort(a+1,a+1+cnt,cmp);
    		st[++top]=1;beg[1]=0;
    		for(int j=1;j<=cnt;j++){
    			if(a[j]==1)continue;
    			int anc=lca(a[j],st[top]);
    			if(anc!=st[top]){
    				while(top>1&&dep[st[top-1]]>dep[anc])
    					add(st[top-1],st[top]),top--;
    				if(st[top-1]!=anc)beg[anc]=0,add(anc,st[top]),st[top]=anc;
    				else add(anc,st[top--]);
    			}
    			beg[a[j]]=0;st[++top]=a[j];
    		}
    		for(int j=1;j<top;j++)
    			add(st[j],st[j+1]);
    		solve(1);
    		printf("%d
    ",dp[1]);
    		for(int j=1;j<=cnt;j++)
    			val[a[j]]=0;
    	}
    	return 0;
    }
    

    深深地感到自己的弱小。

  • 相关阅读:
    MySQL对于数据库应该如何如何配置安全问题了
    对于改善 MySQL 数据装载操作有效率的方法是怎样
    MySQL与SQL比较有那些区别呢
    Centos6.5和Centos7 php环境搭建如何实现呢
    php单例模式是怎么实现的呢
    PHP编写的图片验证码类文件分享方法
    PHP中header函数的用法及其注意重点是什么呢
    java正则表达式四种常用的处理方式是怎么样呢《匹配、分割、代替、获取》
    PHP弱类型安全问题的写法和步骤
    vs2010 使用IIS EXPRESS出错.
  • 原文地址:https://www.cnblogs.com/syzf2222/p/13888293.html
Copyright © 2011-2022 走看看