zoukankan      html  css  js  c++  java
  • CF455C Civilization 树的直径

    问题描述

    LG-CF455C


    题解

    首先,题目给出了 (m) 条边,对这 (n) 个点, (m) 条边组成的森林,跑出每棵树的直径,同时使用并查集维护树的连通性。

    考虑合并两棵树的情况:设这两棵树的代表元为 (u,v) ,这棵树的直径有三种来源:

    • (u) 这棵树的直径

    • (v) 这棵树的直径

    • 穿过 (u,v) 合并边的一条路径

    (u,v) 两棵树的直径是已知的,所以我们只需要考虑最小化第三种情况。

    设树 (u,v) 合并时的点为 (rt_u,rt_v) ,此时第三种情况的值为 (frac{maxdis_{rt_u}}{2}+frac{maxdis_{rt_v}}{2}+1)

    显然,为了最小化两个 (maxdis) ,这两个点选取的一定是原来两棵树直径的中点。


    (mathrm{Code})

    #include<bits/stdc++.h>
    using namespace std;
    
    template <typename Tp>
    void read(Tp &x){
    	x=0;char ch=1;int fh;
    	while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar();
    	if(ch=='-') ch=getchar(),fh=-1;
    	else fh=1;
    	while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    	x*=fh;
    }
    
    const int maxn=300007;
    const int maxm=600007;
    
    int n,m,T;
    vector<int> G[maxn];
    int fa[maxn];
    
    int bel[maxn],cnt;
    
    void add(int x,int y){
    	G[x].push_back(y);
    }
    
    int find(int x){
    	return fa[x]==x?x:fa[x]=find(fa[x]);
    }
    
    int dep[maxn],ans[maxn];
    
    int pos,lst;
    
    void merge(int x,int y){
    	if(find(x)!=find(y)) fa[fa[x]]=fa[y];
    }
    
    void dfs(int x,int col,int dis){
    	if(bel[x]==col) return;
    	if(dis>=lst) lst=dis,pos=x;
    	bel[x]=col;
    	for(int i=0;i<G[x].size();i++){
    		int y=G[x][i];
    		merge(x,y);
    		dfs(y,col,dis+1);
    	}
    }
    
    void Getmax(){
    	int mx=-1;
    	for(int i=1;i<=n;i++){
    		if(dep[i]>mx) mx=dep[i],pos=i;
    	}
    }
    
    void cz1(){
    	int x;read(x);
    	printf("%d
    ",ans[find(x)]);
    }
    
    void cz2(){
    	int x,y;read(x);read(y);
    	int xx=find(x),yy=find(y);
    	if(xx==yy) return;
    	fa[xx]=yy;
    	ans[yy]=max(ans[xx],max(ans[yy],(ans[xx]+1)/2+(ans[yy]+1)/2+1));
    }
    
    void preprocess(){
    	for(int i=1;i<=n;i++) fa[i]=i;
    }
    
    int main(){
    	read(n);read(m);read(T);
    	
    	preprocess();
    	
    	for(int i=1,x,y;i<=m;i++){
    		read(x);read(y);
    		add(x,y);add(y,x);
    	}
    	
    	for(int i=1;i<=n;i++){
    		if(bel[i]) continue;
    		lst=0,pos=i;
    		dfs(i,i,0);
    		lst=0;
    		dfs(pos,pos,0);
    		ans[find(i)]=lst;
    	}
    	
    	int op;
    	while(T--){
    		read(op);
    		if(op==1) cz1();
    		else cz2();
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    拓扑排序笔记
    Codeforces Round #683 (Div. 2, by Meet IT)(A->C)(构造,思维,贪心)
    Acwing 846. 树的重心(DFS枚举删除每一个点)
    Acwing 125. 耍杂技的牛(贪心)(从局部到全局)
    Acwing 802. 区间和(下标离散化+vector+二分)
    Acwing 799. 最长连续不重复子序列(双指针)
    Acwing 139. 回文子串的最大长度(前缀+后缀处理+哈希+二分)
    Linux shell 变量$#,$@,$0....的含义
    一双不锈钢筷子 的测试用例?
    OSI模型 TCP/IP模型 再整理
  • 原文地址:https://www.cnblogs.com/liubainian/p/11815905.html
Copyright © 2011-2022 走看看