求助CFR748div3的E题
  • 板块灌水区
  • 楼主河城白露
  • 当前回复7
  • 已保存回复7
  • 发布时间2021/10/14 08:29
  • 上次更新2023/11/4 03:52:09
查看原帖
求助CFR748div3的E题
27765
河城白露楼主2021/10/14 08:29

求助QaQ 传送门:https://codeforces.com/contest/1593/problem/E 本蒟蒻采用队列存叶子节点的方法进行删叶子操作,但是一直在第二个数据点TLE,没发现代码哪里卡死循环(注,本题所有测试数据中n的总和<=400000,所以删叶子一般不会超时),所以请各位大佬求助,谢谢。(具体代码过程已经有标明注释)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#define ll long long
using namespace std;
const int N=4e5+100;
int hd[N],du[N];
int n,i,t,k,cnt,x,y,rec,kk,ans;
bool vis[N];
struct star{
	int ne,to;
}e[N<<1];//采用链式前向星存边
queue <int> q;//开队列存叶子
void adde(int xx,int yy)
{
	e[++cnt].ne=hd[xx];
	e[cnt].to=yy;
	hd[xx]=cnt;
}
int main()
{
	scanf("%d",&t);
	while(t)
	{
		cnt=rec=ans=0;
		kk=1;
		memset(e,0,sizeof(e));
		memset(hd,0,sizeof(hd));
		memset(du,0,sizeof(du));
		memset(vis,0,sizeof(vis));
		scanf("%d%d",&n,&k);
		for (i=1;i<n;i++)//存边
		{
			scanf("%d%d",&x,&y);
			adde(x,y);
			adde(y,x);
			du[x]++;
			du[y]++;
		}
		if (n <= 2)//显然能全部删除
		{
			printf("0\n");
			t--;
			continue;
		}
		for (i=1;i<=n;i++)
		{
			if (du[i] == 1) //如果是叶子节点的话就存储到队列q并统计叶子个数
			{
				q.push(i);
				rec++;
			}
		}
		while(kk <= k)
		{
			int res=0,ka,j;
			if (rec == 0) break;
			if (kk == k)//如果是第k次操作直接加入预删去的叶子个数
			{
				ans+=rec;
				break;
			}
			while(rec > 0)//第kk次操作需导出rec个节点
			{
				x=q.front();
				q.pop();
				vis[x]=1;//vis标记该边已删除
				rec--;
				ans++;
				if (ans >= n) break;//如果已经删去n个叶子的话就退出循环
				for (j=hd[x];j;j=e[j].ne)
				{
					ka=e[j].to;
					if (vis[ka]) continue;
					du[ka]--;
					if (du[ka] == 1)//删到该节点只有一条边连接时存储该节点
					{
						q.push(ka);
						res++;//统计新叶子个数
					}
				}
			}
			rec=res;//传递叶子个数
			if (ans >= n) break;
			kk++;
		}
		ans=n-ans;
		printf("%d\n",ans);
		while(!q.empty()) q.pop();//清空队列剩余的节点
		t--;
	}
	return 0;
}
2021/10/14 08:29
加载中...