题解 P2195 【HXY造公园】

天哪这道题竟然只有一篇题解!


 

emm,首先读题看完两个操作就已经有很明确的思路了,显然是并查集+树的直径 一波解决。

并查集不多说了,如果不了解的可以看这里.

树的直径的思路很朴实,就是两边DFS(BFS也OK)。具体先随便找一个节点,然后搜一遍,找到最远的,然后再搜一遍,这样合在一起就一定是最长的了。

不过呢这道题还是注意一下求直径的公式,具体如下:

$D_new=max(D_u,D_v,[D_u/2]+[D_v/2]+1)$

那个方括号指的是取整(没找到在哪里打出来)。

en除此之外好像没什么好说的。。。

AC代码如下:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<vector>
 5 using namespace std;
 6 
 7 const int maxn=300300;
 8 
 9 int n,m,q,max_i,max_v;
10 int f[maxn],len[maxn],sz[maxn];
11 bool used[maxn];
12 vector<int>g[maxn];
13 
14 void dfs(int val,int depth,int pos){
15     if(depth>max_i){
16         max_i=depth;
17         max_v=val;
18     }
19     for(int i=0;i<g[val].size();i++){
20         if(g[val][i]!=pos)dfs(g[val][i],depth+1,val);
21     }
22 }
23 
24 int calc(int val){
25     max_i=-1;
26     dfs(val,0,-1);
27     max_i=-1;
28     dfs(max_v,0,-1);
29     return max_i;
30 }
31 
32 int find(int x){
33     if(x==f[x])return x;
34     return f[x]=find(f[x]);
35 }
36 
37 void merge(int x,int y){
38     x=find(x),y=find(y);
39     if(sz[x]>sz[y])swap(x,y);
40     sz[y]+=sz[x];
41     f[x]=y;
42 }
43 
44 int radius(int x){
45     return (len[x]+1)/2;
46 }
47 
48 void merge2(int x,int y){
49     x=find(x),y=find(y);
50     if(x==y)return;
51     if(sz[x]>sz[y])swap(x,y);
52     sz[y]+=sz[x];
53     f[x]=y;
54     len[y]=max(max(radius(x)+radius(y)+1,len[x]),len[y]);
55 }
56 
57 int main() {
58     scanf("%d%d%d",&n,&m,&q);
59     for(int i=1;i<=n;i++){
60         f[i]=i;
61         sz[i]=i;
62         len[i]=0;
63     }
64     for(int i=1;i<=m;i++){
65         int x,y;
66         scanf("%d%d",&x,&y);
67         g[x].push_back(y);
68         g[y].push_back(x);
69         merge(x,y);
70     }
71     for(int i=1;i<=n;i++){
72         int p=find(i);
73         if(!used[p]){
74             used[p]=1;
75             len[p]=calc(i);
76         }
77     }
78     while(q--){
79         int t,x,y;
80         scanf("%d",&t);
81         if(t==1){
82             scanf("%d",&x);
83             printf("%d\n",len[find(x)]);
84         }else{
85             scanf("%d%d",&x,&y);
86             merge2(x,y);
87         }
88     }
89 }

转载于:https://www.cnblogs.com/ilverene/p/9819088.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值