• CF455C Civilization | luogu HXY造公园


    题目链接:
    https://www.luogu.org/problemnew/show/P2195
    http://codeforces.com/contest/455/problem/C

    显然我们可以想到要用并查集来维护联通节点的信息。

    然后题目要求的是合并之后树的直径最小。

    然后我们可以知道在两个树的中点合并是最好的。所以我们设(len[i])为i所在树的直径,那么按照上述策略,合并(i,j)之后新树的直径就是(max(len[i],len[j],(len[i]+1)/2+(len[j]+1)/2+1))

    接下来就是。。树的直径怎么求?

    两遍bfs或者dfs就行了qwq

    第一遍先找到当前点最远的点pos,之后从pos开始找离pos最远的点到pos的距离就是树的直径了。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define MAXN 300010
    using namespace std;
    inline int read()
    {
    	int x=0,f=1; char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    	return x*f;
    }
    int n,m,que,edge_number,pos,ans,root;
    int fa[MAXN],len[MAXN],head[MAXN],done[MAXN],dis[MAXN];
    struct Edge{int nxt,to;}edge[MAXN<<1];
    inline int maxx(int x,int y,int z){return max(max(x,y),z);}
    inline void add(int from,int to)
    {
    	edge[++edge_number].to=to;
    	edge[edge_number].nxt=head[from];
    	head[from]=edge_number;
    }
    inline int find(int x)
    {
    	if(fa[x]==x) return x;
    	else return fa[x]=find(fa[x]);
    }
    inline void merge(int x,int y)
    {
    	int a=find(x),b=find(y);
    	if(a==b) return;
    	if(len[a]<len[b]) swap(a,b);
    	fa[b]=a; 
    	len[a]=maxx(len[a],len[b],(len[a]+1)/2+(len[b]+1)/2+1);
    }
    inline void search(int now,int pre,int sum)
    {
    	fa[now]=root;
    	if(sum>ans)
    		ans=sum,pos=now;
    	for(int i=head[now];i;i=edge[i].nxt)
    		if(edge[i].to!=pre)
    			search(edge[i].to,now,sum+1);
    }
    int main()
    {
    	n=read(),m=read(),que=read();
    	for(int i=1;i<=n;i++) fa[i]=i;
    	for(int i=1;i<=m;i++)
    	{
    		int u,v;
    		u=read(),v=read();
    		add(u,v);
    		add(v,u);
    	}
    	for(int i=1;i<=n;i++)
    	{
    		if(fa[i]!=i) continue;
    		root=pos=i; 
    		ans=0; 
    		search(i,0,0);
    		ans=0; 
    		search(pos,0,0);
    		len[i]=ans;
    	}
    	for(int i=1;i<=que;i++)
    	{
    		int name,u,v,k;
    		name=read();
    		if(name==2)
    			u=read(),v=read(),merge(u,v);
    		else 
    			k=read(),printf("%d
    ",len[find(k)]);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    动态库 DLL 封装二:dll封装方法
    动态库 DLL 封装一:dll分类
    C++读取配置文件ini
    WCHAR 字符串拼接
    关于web桌面应用的集成解决方案
    CSS Grid网格布局(转)
    使用 antd 的 form 组件来自定义提交的数据格式
    syslogd日志的一些作用
    我的三年感悟——避免无尽的自我内耗
    《被讨厌的勇气》读后感
  • 原文地址:https://www.cnblogs.com/fengxunling/p/9915351.html
Copyright © 2020-2023  润新知