首页 > 其他分享 >CF455C Civilization 题解

CF455C Civilization 题解

时间:2024-04-13 22:55:51浏览次数:19  
标签:CF455C 题解 xx yy int length Civilization maxn 直径

思路

  1. 求树的直径,并存在一个数组里。
  2. 用并查集来动态合并加维护区域信息(包括同一颗树里的有着相同祖先的点的合并,不同树之间的合并)。
  3. 假设 \(length\) 数组:对于每棵树的根节点 \(x\),\(length_{x}=\) 该树的直径长度

接下来对于每个询问(如果给出的两点在同一颗树内则忽略),利用并查集找出两棵树的根节点 x,y,并用并查集合并两棵树,
合并后树的直径为 \(\max{[(length_{x}+1)\div2+(length_{y}+1)\div 2+1],length_{x},length_{y}}\)。

因为要想直径最短,我们选择加边的点一定要在直径上,因为其他的点走到直径还要一段距离,从而增长了路径。那么直径就被选择的点分成了两段。因为我们要最小化较长的那一段,所以要让选择的点尽量靠近直径的中点。最后的答案就是 直径长度的一半向上取整。并且还要考虑原先两棵树本来就存在的直径,他们仨进行比较,最大的才是合并后的树的直径。

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
const int inf=0x3f3f3f3f;
typedef long long ll;
struct Edge {
	int from,to;
};
vector<Edge>edges;
vector<int>G[maxn];
void add(int from,int to)
{
	edges.push_back({from,to});
	int m=edges.size();
	G[from].push_back(m-1);
}
bool vis[maxn],vis2[maxn];
int pos,cnt;
int length[maxn],fa[maxn];
void dfs(int x,int len)
{
	if(len>cnt) {
		pos=x;
		cnt=len;
	}
	vis[x]=true;
	for(int i=0; i<G[x].size(); i++) {
		Edge e=edges[G[x][i]];
		int u=e.to;
		if(!vis[u]) {
			dfs(u,len+1);
		}
	}
	vis[x]=false;
}
int cal(int x)//找树的直径
{
	cnt=-1;
	dfs(x,0);
	cnt=-1;
	dfs(pos,0);
	return cnt;
}
int find (int x)
{
	return fa[x]==x?x:fa[x]=find(fa[x]);
}
void merge(int x,int y)
{
	int xx=find(x),yy=find(y);
	fa[xx]=yy;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	memset(vis,0,sizeof(false));
	memset(vis2,0,sizeof(false));
	int n,m,q;
	cin>>n>>m>>q;
	for(int i=1; i<=n; i++)
		fa[i]=i;
	for(int i=1; i<=m; i++) {
		int x,y;
		cin>>x>>y;
		add(x,y);
		add(y,x);
		merge(x,y);
	}
	for(int i=1; i<=n; i++) {
		if(fa[i]!=i||vis2[i])//因为有并查集的存在,所以只对树的根节点进行操作
			continue;
		vis2[i]=true;//标记
		length[i]=cal(i);
	}
	while(q--) {
		int op,x,y;
		cin>>op>>x;
		if(op==1) {
			cout<<length[find(x)]<<endl;
			continue;
		} else {
			cin>>y;
			int xx=find(x),yy=find(y);
			if(xx==yy)
				continue;
			int temp=((length[xx]+1)/2)+((length[yy]+1)/2)+1;
			temp=max(temp,max(length[xx],length[yy]));
			merge(x,y);//合并
			length[yy]=temp;//更新
		}
	}
}

标签:CF455C,题解,xx,yy,int,length,Civilization,maxn,直径
From: https://www.cnblogs.com/BadBadBad/p/18133537/CF455C

相关文章

  • [题解]SP10606 Balanced Numbers
    SP10606BalancedNumbers关于优化方式的说明详见数位dp例题及详解-下。SPOJ注册不上所以暂时无法提交w,但是3份代码与正解对拍没有问题。使用\(vis[0\sim9]\)表示\(0\sim9\)的访问情况,\(sta[0\sim9]\)表示\(0\sim9\)填写个数的奇偶性(奇数为\(1\),偶数为\(0\))。暴搜先打出来,......
  • 第十五届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组题解
    试题A:握手问题本题总分:\(5\)分思路:组合计数,用为\(50\)个人握手的总方案数\(C^{2}_{50}\),减去七个人彼此没有握手握手的方案数\(C^{2}_{7}\)即为答案。A:握手问题#include<bits/stdc++.h>#defineintlonglong#definedblongdouble#defineall(f)f.begin()......
  • CF1923B Monsters Attack! 题解
    题目简述数轴上有$n$个怪兽。最初第$i$个怪兽在$x_i$位置上,且血量为$a_i$。你在位置$0$上。在每秒钟会发生:你给任意怪兽发射总共$k$颗子弹,受到攻击的怪兽血量减一。血量小于等于$0$的怪兽死亡。没有死亡的怪兽向你移动一个单位。当一个怪兽来到你的位置,你就输......
  • CF1165E Two Arrays and Sum of Functions 题解
    题目简述已知两个长度均为$n$的数组$a$和$b$。给定一个函数:$f(l,r)=\sum\limits_{l\lei\ler}a_i\cdotb_i$。你的任务是对数组$b$中的元素以任意的顺序重新排序,使$\sum\limits_{1\lel\ler\len}f(l,r)$的值最小。题目分析我们首先进行化简,发现题......
  • CF107A Dorm Water Supply 题解
    题目简述给出一个$n$个点,$m$条边的有向图,边带权。保证每个点的出度和入度最多为$1$。对于每一个入度为$0$,出度为$1$的点,我们在该点建一个水箱。对于每一个入度为$1$,出度为$0$的点,我们在该点建一个水龙头。可以发现,每一个水箱对应一个唯一的水龙头,我们将每对对应......
  • CF1942B Bessie and MEX 题解
    题目简述给定一个长度为$n$的数组$a$,让你构造一个等长的排列$p$,其中从$0$到$n-1$的每个整数恰好出现一次。满足对于每一个位置$a_i=\texttt{MEX}(p_1,p_2,\ldots,p_i)-p_i$,其中数组的$\texttt{MEX}$是不在该数组中出现的最小非负整数。题目分析我们发现正着做并......
  • CF244B Undoubtedly Lucky Numbers 题解
    题目简述给定一个$n$,问有多少个小于等于$n$的数只由两个不同的数字$x$和$y$组成。题目分析直接枚举肯定不行,我们考虑枚举$x$和$y$,再利用深搜,生成所有不大于$n$且只由$x$和$y$组成的数字,利用map去重,统计答案即可。代码#include<iostream>#include<map>usi......
  • 2023CCPC题解
    2023年第五届河南省CCPC大学生程序设计竞赛ProblemA.小水獭游河南#include<bits/stdc++.h>usingnamespacestd;intmain(){intt;cin>>t;while(t--){stringa;cin>>a;intst[27],ji=0;memset(st,0,sizeof(......
  • CF1946B Maximum Sum 题解
    题目简述你有一个由$n$个整数组成的数组$a$。你要对它进行$k$次操作。在一次操作中,你选择了数组$a$的任意连续子数组(可能为空),并在数组的任意位置插入了该子数组的和。你的任务是找出经过$k$次操作后数组的最大和。题目分析这道题显然是一道贪心题。对于第$1$次操......
  • 集合计数——题解
    题目这篇题解的背景。。。(可以跳过,与题目无关)说实话,有点恼,也觉得自己有点唐,在以为自己已经理解了变量意义的情况下(实际上并没有)去推了半天错式子,甚至我推出了他不对时还给自己否定了,昨天晚三还拉着\(9G\)与我一块推。。。,结果上午发觉好像意义理解错了。。。抽象,就当是一种......