题目链接:http://codeforces.com/contest/455/problem/C
题意:给出一个图(不一定所有点都连在一起),两种操作:1、合并两个点所在的图,边随意添加,不过要使得加完之后的连通图的最长路最小。2、求点x所在图的最长路。
思路:先把每部分子图的树的直径求出来,然后用并查集维护,合并两个集合后的最长路可能是两个图原最长路各取一半向上取整之和再加上联通的那条路,或者是两个图原来的最长路。
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <utility>
using namespace std;
#define rep(i,j,k) for (int i=j;i<=k;i++)
#define Rrep(i,j,k) for (int i=j;i>=k;i--)
#define Clean(x,y) memset(x,y,sizeof(x))
#define LL long long
#define ULL unsigned long long
#define inf 0x7fffffff
#define mod 100000007
const int maxn = 300009;
int n,m,Q;
int rec,d,ans;
bool f[maxn];
int father[maxn];
int num[maxn];
int Head[maxn];
struct node
{
int next,to;
}edge[maxn*2];
int read()
{
int ans = 0;
char c;
while( !isdigit( c = getchar() ) ) c = getchar();
while( isdigit( c ) )
{
ans = ans * 10 + c - '0';
c = getchar();
}
return ans;
}
int tot = 0;
void add(int a,int b)
{
tot++;
edge[tot].to = b;
edge[tot].next = Head[a];
Head[a] = tot;
}
int getfather( int x )
{
return father[x] == x?x:father[x] = getfather(father[x]);
}
void unio(int a,int b , int k = 0)
{
int fa = getfather(a);
int fb = getfather(b);
if ( fa != fb )
{
if ( k )
{
num[fa] = max( max( num[fa] , num[fb] ) , (num[fb]+1)/2 + ( num[fa] + 1 )/2 + 1 );
}
father[fb] = fa;
}
}
void dfs( int now , int pre , int deep )
{
if ( deep > ans )
{
ans = deep;
rec = now;
}
for( int i = Head[now] ; i != -1; i = edge[i].next )
{
if ( edge[i].to == pre ) continue;
dfs( edge[i].to , now , deep + 1 );
}
}
void init()
{
int a,b;
n = read();
m = read();
Q = read();
rep(i,1,n)
father[i] = i;
Clean(num,0);
Clean(Head,-1);
rep(i,1,m)
{
a = read();
b = read();
unio(a,b);
add(a,b);
add(b,a);
}
Clean(f,false);
rep(i,1,n)
{
if( !f[getfather( i )] )
{
f[ getfather(i) ] = true;
rec = i ;
ans = -1;
dfs( i , i , 0 );
ans = -1;
dfs( rec , rec , 0 );
num[ getfather(i) ] = ans;
}
}
}
void solve()
{
int op;
int x,y;
rep(i,1,Q)
{
op = read();
if ( op == 1 )
{
x = read();
printf("%d\n",num[getfather(x)]);
}
else
{
x = read();
y = read();
unio(x,y,1);
}
}
}
int main()
{
init();
solve();
return 0;
}