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

    题意

    显然是虚树。

    建出虚树后就可以跑DP了。

    (f[x])表示(x)的子树内需要选几个点。

    如果一个点(x)的子树中有选中点(注意不是关键点,因为关键点中有lca)就标记为1。

    之后对当前点分类讨论:

    1.当前点是选中点:显然儿子中子树内有选中点的都要删去

    2.当前点不是选中点:如果儿子中子树内有选中点的个数大于1,那么这个点就删去

    code:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100010;
    int n,m,cnt,t,top,tim;
    int head[maxn],dep[maxn],sta[maxn],a[maxn],dfn[maxn],ans[maxn],size[maxn];
    int f[maxn][20];
    bool flag;
    bool check[maxn];
    struct edge{int to,nxt;}e[maxn<<1];
    vector<int>V[maxn];
    inline int read()
    {
    	char c=getchar();int res=0,f=1;
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
    	return res*f;
    }
    inline bool cmp(int x,int y){return dfn[x]<dfn[y];}
    inline void add(int u,int v)
    {
    	e[++cnt].nxt=head[u];
    	head[u]=cnt;
    	e[cnt].to=v;
    }
    void dfs_pre(int x,int fa)
    {
    	dep[x]=dep[fa]+1;dfn[x]=++tim;
    	for(int i=1;i<=t;i++)f[x][i]=f[f[x][i-1]][i-1];
    	for(unsigned int i=0;i<V[x].size();i++)
    	{
    		int y=V[x][i];
    		if(y==fa)continue;
    		f[y][0]=x;dfs_pre(y,x);	
    	}
    }
    inline int lca(int x,int y)
    {
    	if(dep[x]>dep[y])swap(x,y);
    	for(int i=t;~i;i--)if(dep[f[y][i]]>=dep[x])y=f[y][i];
    	if(x==y)return x;
    	for(int i=t;~i;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
    	return f[x][0];
    }
    inline void build(int k,int* a)
    {
    	cnt=0;
    	sort(a+1,a+k+1,cmp);	
    	sta[top=1]=1;head[1]=0;
    	for(int i=1;i<=k;i++)
    	{
    		if(a[i]==1)continue;
    		int x=lca(a[i],sta[top]);
    		if(x!=sta[top])
    		{
    			while(dfn[sta[top-1]]>dfn[x])add(sta[top-1],sta[top]),top--;
    			if(dfn[sta[top-1]]!=dfn[x])head[x]=0,add(x,sta[top]),sta[top]=x;
    			else add(x,sta[top--]);
    		}
    		head[a[i]]=0;
    		sta[++top]=a[i];
    	}
    	for(int i=1;i<=top-1;i++)add(sta[i],sta[i+1]);
    }
    void dfs(int x,int fa)
    {
    	ans[x]=size[x]=0;
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		int y=e[i].to;
    		if(y==fa)continue;
    		dfs(y,x);
    		ans[x]+=ans[y];size[x]+=size[y];
    	}
    	if(check[x])ans[x]+=size[x],size[x]=1;
    	else if(size[x]>1)size[x]=0,ans[x]++;
    }
    int main()
    {
    	n=read();t=(int)log2(n)+1;
    	for(int i=1;i<n;i++)
    	{
    		int u=read(),v=read();
    		V[u].push_back(v),V[v].push_back(u);
    	}
    	dfs_pre(1,0);
    	m=read();
    	for(int i=1;i<=m;i++)
    	{
    		flag=0;
    		int k=read();
    		for(int j=1;j<=k;j++)a[j]=read(),check[a[j]]=1;
    		for(int j=1;j<=k;j++)if(check[f[a[j]][0]]){puts("-1"),flag=1;break;}
    		if(flag)
    		{
    			for(int j=1;j<=k;j++)check[a[j]]=0;
    			continue;
    		}
    		build(k,a);dfs(1,0);
    		printf("%d
    ",ans[1]);
    		for(int j=1;j<=k;j++)check[a[j]]=0;
    	}
    	return 0;
    }
    
  • 相关阅读:
    CleanWebpackPlugin
    webpack
    kubeadm部署k8s
    leetcode 148 链表排序的归并排序和插入排序
    102 二叉树层序遍历(一下出一层的广搜和DFS)
    139 单词拆分 dp
    48 旋转图像 水平翻转然后主对角线翻转即可实现顺时针旋转90°
    31下一个排列
    最长连续序列
    每日总结22——SQL语句(保持现有内容在后面增加内容)
  • 原文地址:https://www.cnblogs.com/nofind/p/11969651.html
Copyright © 2011-2022 走看看