首页 > 其他分享 >CF51F Caterpillar题解

CF51F Caterpillar题解

时间:2023-04-30 16:22:15浏览次数:59  
标签:SZ ver CF51F 题解 leaves mark int Caterpillar res

题目传送门

题意:定义毛毛虫为一种特殊的树,形如一条链上挂着若干个叶子。特殊地,在本题中的毛毛虫允许自环但不允许重边。给定一个无向图,每次操作可以合并两个点以及两个点的出边(两个点有相同出边则出现重边,两个点之间有边则出现自环)。求将其变为毛毛虫的最小操作次数。

容易发现,一个环要想最终放到一棵树上,必然要缩成一个点(加若干自环),否则一定出现重边。于是可以先用边双连通缩点,转化成对森林的操作。

求最小的操作数等价于求最多的剩余点。如果钦定了选哪条链,则可以将链的邻居选作叶子,并将更远的点合并到这些邻居上。但是,这样做并不优,因为我们可以将链的某个邻居与链合并起来,于是该邻居的邻居就会成为叶子,显然这样不会变的更劣(只要有邻居的邻居存在)。于是,反复操作即可得出结论:最终的选法一定是选一条链以及所有叶子。于是可进一步得出结论:该链一定为树的直径。

最后对于不同连通块,只需要用 \(cnt-1\) 次操作合并起来即可。注意需要特判(缩完点后)只有一个点的连通块。

By dzhulgakov

#define N 2222
int n,m;
VI a[N],b[N];
int mark[N],tmm[N],tick;
int nn,gid[N];
VI stack;
 
int dfs1(int v, int parent)
{
	int res = tmm[v] = tick++;
	mark[v] = 1;
	stack.pb(v);
	REP(i,SZ(a[v]))
	{
		int ver = a[v][i];
		if (ver == parent) continue;
		if (mark[ver])
			res = min(res, tmm[ver]);
		else
			res = min(res, dfs1(ver,v));
	}
	mark[v] = 2;
	if (res == tmm[v])
	{
		gid[v] = nn;
		while (stack.back() != v)
		{
			gid[stack.back()] = nn;
			stack.pop_back();
		}
		stack.pop_back();
		nn++;
	}
	return res;
}
 
int glmax,total;
 
PII dfs2(int v, int parent)
{
	mark[v]=1;
	VI q;
	int res = 0;
	int leaves = 0;
	REP(i,SZ(b[v]))
	{
		int ver = b[v][i];
		if (ver == parent) continue;
		PII x = dfs2(ver,v);
		leaves += x.second;
		q.pb(x.first-x.second);
	}
	if (q.empty())
		leaves++;
	REP(i,SZ(q))
		res = max(res, q[i]+leaves+1);
	res = max(res, leaves);
	SORT(q);
	if (SZ(q) >= 2)
	{
		glmax = max(glmax, q[SZ(q)-1]+q[SZ(q)-2]+1-(parent==-1&&SZ(b[v])==1));
	}
	glmax = max(glmax,res-leaves-(parent==-1&&SZ(b[v])==1));
	if (parent==-1&&SZ(b[v])==1) leaves++;
	return PII(res,leaves);
}
 
int main()
{
	//freopen("data.in","r",stdin);
	scanf("%d%d",&n,&m);
	REP(i,m)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		x--;y--;
		a[x].pb(y);
		a[y].pb(x);
	}
	CLEAR(mark);
	FILL(gid,-1);
	tick = 0;
	nn = 0;
	REP(i,n) if (mark[i]==0)
	{
		stack.clear();
		dfs1(i,-1);
	}
	int res = 0;
	REP(i,n) REP(j,SZ(a[i]))
		if (gid[a[i][j]] != gid[i])
			b[gid[i]].pb(gid[a[i][j]]);
	CLEAR(mark);
	bool fst = true;
	REP(i,nn) if (mark[i] == 0)
	{
		if (b[i].empty())
			res++;
		else
		{
			glmax = 0;
			int leaves = dfs2(i,-1).second;
			res += glmax+leaves;
		}
		if (fst)
			fst = false;
		else
			res--;
	}
	res = n - res;
	printf("%d\n",res);
	return 0;
}

标签:SZ,ver,CF51F,题解,leaves,mark,int,Caterpillar,res
From: https://www.cnblogs.com/cxm1024/p/17365390.html

相关文章

  • Windows下安装Docker详细过程及问题解决
    官方手册供参考:https://docs.docker.com/desktop/windows/一:什么是Docker?Docker是一个开放源代码软件,是一个开放平台,用于开发应用、交付(shipping)应用、运行应用。Docker允许用户将基础设施(Infrastructure)中的应用单独分割出来,形成更小的颗粒(容器),从而提高交付软件的速度。Dock......
  • 义中常规赛430题解
    T1二分一个删除的数字个数然后考虑删除的数字肯定是从大到小来的,所以预处理一个降序的数组,这样能知道二分的数字个数所对应的数字。在原数组上跑最大子段和,如果碰到大于二分位置的数字就删了。最终成绩26分,因为对于二分的个数mid,原数组中a[mid]不止1个的话,无法判断哪些该删,哪......
  • Android Bitmap内存溢出问题解释
    Android平台在图片处理方面经常会出现OOM的问题,在去年开发的一个项目中,我也一直被这个问题所困扰,在这方面也搜集了许多的资料,今天仅仅针对Android平台的Bitmap说事儿,今后再对内存的问题做详细的探讨,android平台对图片解码这块确实设置的有内存上限,在解码Bitmap的时候android平台会......
  • abc252_d Distinct Trio 题解
    这是数学题耶!题意给定一个整数\(n\)和一个长度为\(n\)的整数序列\(a\),求满足以下要求的三元组个数:\(1\leqslanti<j<k\leqslantn\)。\(a_i\nea_j\),\(a_j\nea_k\),\(a_k\nea_i\)。思路先想正着做,好,不会。正着做不行就反着做,先算出所有情况,再去掉不合法。......
  • ABC G Ex 简要题解
    ABC212GPowerPair推柿子题\(\sum\limits_{x}^{P-1}\sum\limits_{y}^{P-1}\existsn\in\mathbb{N}\x^n\equivy(\bmodP)\)\(1+\sum\limits_{x=1}^{P-1}\sum\limits_{y=1}^{P-1}\existsn\in\mathbb{N}\x^n\equivy(\bmodP)\)考虑模\(P\)......
  • AT_abs300_e 题解
    一、题目描述:你有一个骰子,数字1~6可以被等概率扔到。初始时有一个数$ans=1$。当扔到数字$x$时,$ans=ans\timesx$。给你一个数字$n$,求$ans$能等于$n$的概率。$n<=1e18$。答案对$998244353$取模。 二、解题思路:当扔到$1$时,相当于......
  • 皇后游戏 题解
    luoguP2123题目描述皇后有\(n\)位大臣,每位大臣的左右手上面分别写上了一个正整数。恰逢国庆节来临,皇后决定为\(n\)位大臣颁发奖金,其中第\(i\)位大臣所获得的奖金数目为第\(i-1\)位大臣所获得奖金数目与前\(i\)位大臣左手上的数的和的较大值再加上第\(i\)位大臣右手......
  • 题解
    D.RangeandPartition1800思维https://codeforces.com/contest/1631/problem/D题解:由于严格大于,故其最终前缀和s[n]>=k,而当s[n]>=k,s[0]=0,每步至多下降1,故其中必有至少k个点满足s[i]=x(1<=x<=k),故符合题意,故只需双指针找出最小的满足题意的区间即可。#include<bits/stdc++......
  • 4 月 27 日测试题解
    4月27日测试题解最短路专场T1\({\color{green}{\text{100pts}}}\text{/100pts}\)题意给出\(m\)个变量与\(n\)个约束,每个约束形如以下三种中的一种;\(x_i-x_j\lew\)\(x_i-x_j\gew\)\(x_i-x_j=w\)有\(q\)个询问,每个询问为形如\((x_i,x_j)\)的二元......
  • 4 月 21 日测试题解
    4月21日测试题解T1\({\color{green}{\text{100pts}}}\text{/100pts}\)题意给出平面上的两条线段,求线段之间的距离。\(\text{|线段端点坐标|}\le10^4\)。思路一开始想的是分讨,但是又怕自己写挂了,所以就写了三分套三分。至少这个不怕少讨论一个情况。既然是三分套三分,......