zoukankan      html  css  js  c++  java
  • CF1385F Removing Leaves 拓扑排序

    题意

    给定一棵树,现在定义一次操作为"选定拥有同样父亲的 (k) 个叶节点,并将这 (k) 个叶节点一起删去。问最多能够进行多少次操作。

    范围&性质: (1le kle nle 2 imes 10^5)

    分析:

    由于这是一颗无根树,所以我们无法求出DFS每个点的儿子和父亲

    那么我们换个角度考虑,每次被删除的点有什么特点,我们发现它们的度数都是1

    也就是说我们按照拓扑排序的方法将度数为1的点删掉,同时一个点能成为叶子的前提条件有两个:

    1. 它的儿子都能删掉(直接或间接成为叶子)
    2. 它的儿子的个数为 (k) 的倍数(否则它的儿子删不完全)

    对于根节点要特殊处理,因为别的点都有一个父亲,但根节点没有,所以最后统计答案时要将根节点的度数 (+1)

    代码:

    #include<bits/stdc++.h>
    
    using namespace std;
    
    namespace zzc
    {
    	inline int read()
    	{
    		int x=0,f=1;char ch=getchar();
    		while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
    		while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    		return x*f;
    	}
    	
    	const int maxn = 2e5+5;
    	int t,n,k,ans,cnt=0,idx,st;
    	int head[maxn],deg[maxn],val[maxn];
    	bool vis[maxn];
    	struct edge
    	{
    		int to,nxt;
    	}e[maxn<<1];
    	queue<int> q;
    	
    	void add(int u,int v)
    	{
    		e[++cnt].to=v;
    		e[cnt].nxt=head[u];
    		head[u]=cnt;
    		deg[v]++;
    	}
    	
    	void toposort()
    	{
    		while(!q.empty()) q.pop();
    		for(int i=1;i<=n;i++) if(deg[i]==1) q.push(i);
    		while(!q.empty())
    		{
    			int u=q.front();q.pop();
    			if(vis[u]) continue;
    			vis[u]=true;
    			for(int i=head[u];i;i=e[i].nxt)
    			{
    				int v=e[i].to;
    				if(!vis[v])
    				{
    					val[v]++;
    					if(val[v]%k==0&&val[v]==deg[v]-1) q.push(v);	
    				}
    			}
    		}
    		for(int i=1;i<=n;i++) ans+=val[i]/k;
    	}
    	
    	void work()
    	{
    		int a,b;
    		t=read();
    		while(t--)
    		{
    			cnt=0;ans=0;idx=0;
    			for(int i=1;i<=n;i++) head[i]=deg[i]=val[i]=0,vis[i]=false;
    			n=read();k=read();
    			for(int i=1;i<n;i++)
    			{
    				a=read();b=read();
    				add(a,b);add(b,a);
    			}
    			if(k==1)
    			{
    				printf("%d
    ",n-1);
    				continue;
    			}
    			toposort();
    			printf("%d
    ",ans);
    		}
    	
    	}
    
    }
    
    int main()
    {
    	zzc::work();
    	return 0;
    }
    
  • 相关阅读:
    [NOIP2013提高组] CODEVS 3287 火车运输(MST+LCA)
    BZOJ 2763: [JLOI2011]飞行路线(最短路)
    BZOJ 1083: [SCOI2005]繁忙的都市(MST)
    USACO Seciton 5.4 Canada Tour(dp)
    HDOJ 3415 Max Sum of Max-K-sub-sequence(单调队列)
    POJ2823 Sliding Window(单调队列)
    USACO Section 5.4 TeleCowmunication(最小割)
    [IOI1996] USACO Section 5.3 Network of Schools(强连通分量)
    USACO Section 5.3 Milk Measuring (IDDFS+dp)
    USACO Section 5.3 Big Barn(dp)
  • 原文地址:https://www.cnblogs.com/youth518/p/13984230.html
Copyright © 2011-2022 走看看