zoukankan      html  css  js  c++  java
  • 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;
    }
    
    
  • 相关阅读:
    两路归并算法
    个性化搜索引擎调研(三)
    编程珠玑开篇磁盘文件排序问题
    Lucene里经常被聊到的几个话题
    成就霸业的座右铭(绝对经典)
    别人对你的态度,决定了你的命运
    iBATIS缓存实现分析[转]
    Taste/Thoth:Taste Architecture 概览【转Beyond Search】
    中文分词算法笔记
    ConcurrentModificationException主要原因及处理方法
  • 原文地址:https://www.cnblogs.com/fengxunling/p/9915351.html
Copyright © 2011-2022 走看看