题意:给你一个森林,有q个操作,操作分两种
1)询问节点x所在树的最长链。
2) 将x所在和y所在的树用一条边连起来且使得这颗新树的最长边最短。(在一起不用连)
解题思路:其实这个算法主要的瓶颈就是在合并两颗树上面使得这个新树最长边最短,这里我们考虑到,我们并没有破坏两颗树的结构 ,所以 它们内部的最长边还是保持的。 那么最长边的唯一不确定性是来自于连接两颗树的链, 怎么样使得这条链所在的最长链最小呢,其实只需要分别找到两颗树中 点到其他点最长链最小的那个点然后把它们连起来 , 又可以知道 这两个点 必定是 两颗树最长链子的中点(证:树是相通的,其他点都会链接到最长链子上面的。) 然后再借以并查集辅助,就可以解决这个题目了。
解题代码:
1 // File Name: 455c.cpp 2 // Author: darkdream 3 // Created Time: 2015年03月13日 星期五 15时56分13秒 4 5 #include<vector> 6 #include<list> 7 #include<map> 8 #include<set> 9 #include<deque> 10 #include<stack> 11 #include<bitset> 12 #include<algorithm> 13 #include<functional> 14 #include<numeric> 15 #include<utility> 16 #include<sstream> 17 #include<iostream> 18 #include<iomanip> 19 #include<cstdio> 20 #include<cmath> 21 #include<cstdlib> 22 #include<cstring> 23 #include<ctime> 24 #define LL long long 25 #define maxn 310005 26 using namespace std; 27 int n , m,q; 28 int fa[maxn]; 29 vector<int> mp[maxn]; 30 int mi[maxn]; 31 int find(int x) 32 { 33 return fa[x] == x?x:fa[x] = find(fa[x]); 34 } 35 int tmp ; 36 int dfs(int k , int la) 37 { 38 int mx = 0 ; 39 int tt = 0 ; 40 for(int i = 0 ;i < mp[k].size() ;i ++) 41 { 42 if(mp[k][i] == la) 43 continue; 44 tt = dfs(mp[k][i],k); 45 tmp = max(tmp,tt + mx); 46 mx = max(tt,mx); 47 } 48 return mx + 1; 49 } 50 int main(){ 51 scanf("%d %d %d",&n,&m,&q); 52 int ta , tb; 53 for(int i= 1;i <= n;i ++) 54 { 55 fa[i] = i ; 56 } 57 int tmpa, tmpb; 58 for(int i = 1;i <= m; i ++) 59 { 60 scanf("%d %d",&ta,&tb); 61 mp[ta].push_back(tb); 62 mp[tb].push_back(ta); 63 tmpa = find(ta); 64 tmpb = find(tb); 65 if(tmpa != tmpb) 66 { 67 fa[tmpa] = fa[tmpb]; 68 } 69 } 70 for(int i = 1;i <= n;i ++) 71 { 72 if(fa[i] == i) 73 { 74 tmp = 0 ; 75 dfs(i,0); 76 mi[i] = tmp ; 77 } 78 } 79 int status,l,r; 80 for(int i = 1;i <= q;i ++) 81 { 82 scanf("%d",&status); 83 if(status == 1) 84 { 85 scanf("%d",&l); 86 printf("%d ",mi[find(l)]); 87 }else{ 88 scanf("%d %d",&l,&r); 89 int tmpa = find(l); 90 int tmpb = find(r); 91 if(tmpa != tmpb) 92 { 93 fa[tmpa] = fa[tmpb]; 94 int tta = mi[tmpa]%2 == 1?mi[tmpa]/2+1:mi[tmpa]/2; 95 int ttb = mi[tmpb]%2 == 1?mi[tmpb]/2+1:mi[tmpb]/2; 96 mi[tmpb] = max(tta + ttb + 1,mi[tmpb]); 97 mi[tmpb] = max(mi[tmpb],mi[tmpa]); 98 } 99 } 100 /*printf(" "); 101 for(int i = 1;i <= n;i ++) 102 printf("%d ",mi[i]); 103 printf(" "); 104 */ 105 } 106 return 0; 107 }