【luogu P2195 HXY造公园】 题解

题目链接:https://www.luogu.org/problemnew/show/P2195

fir.吐槽题目(省略1w字

sec.考虑对一个森林的维护,每棵树用并查集维护。
操作1:输出当前查询点的树的直径
操作2:对于两条直径连接起来最短,肯定是连两个中点(显而易见

thi.小trick:重复利用vis数组—变成int,这样对于每棵树实际每个根不一样标号时的vis值也不同

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 3 * 1e5 + 10;
inline int read()
{
    int k=0,f=1;
    char c=getchar();
    while(!isdigit(c))
    {
        if(c=='-')f=-1;
        c=getchar();
    }
    while(isdigit(c))
    {
        k=(k<<1)+(k<<3)+c-48;
        c=getchar();
    }
    return k*f;
}
struct edge{
	int from, to, next, len;
}e[maxn<<2];
int cnt, head[maxn];
int dis[maxn], node, path[maxn], n, m, Q, fa[maxn], ans, vis[maxn];
void add(int u, int v, int w)
{
	e[++cnt].from = u;
	e[cnt].to = v;
	e[cnt].len = w;
	e[cnt].next = head[u];
	head[u] = cnt;
}
int find(int x)
{
	return fa[x] == x ? x : fa[x] = find(fa[x]);
}

int bfs(int s)
{
	queue<int> q;
	vis[s] = s;
	dis[s] = 0;
	q.push(s);
	int node, d = 0;
	while(!q.empty())
	{
		int now = q.front(); q.pop();
		for(int i = head[now]; i != -1; i = e[i].next)
		{
			if(vis[e[i].to] != s)
			{
				dis[e[i].to] = dis[now] + e[i].len;
				vis[e[i].to] = s; 
				q.push(e[i].to);
				if(dis[node] < dis[e[i].to])
				{
					node = e[i].to;
					d = dis[e[i].to];
				}	
			}
		}
	}
	dis[node] = 0;
	vis[node] = node;
	q.push(node);
	while(!q.empty())
	{
		int now = q.front(); q.pop();
		for(int i = head[now]; i != -1; i = e[i].next)
		{
			if(vis[e[i].to] != node)
			{
				dis[e[i].to] = dis[now] + e[i].len;
				vis[e[i].to] = node; 
				q.push(e[i].to);
				if(d < dis[e[i].to])
				d = dis[e[i].to];
			}
		}
	}
	return d;
}
int main()
{
	memset(head, -1, sizeof(head));
	n = read(); m = read(); Q = 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, 1), add(v, u, 1);
		if(find(u) != find(v))
		fa[find(u)] = find(v);
	}
	for(int i = 1; i <= n; i++)
	{
		if(i == find(i)) path[i] = bfs(i);
	}
	for(int i = 1; i <= Q; i++)
	{
		int opt, x, y;
		opt = read();
		if(opt == 1)
		{
			x = read();
			printf("%d\n", path[find(x)]);
		}
		else
		{
			x = read(); y = read(); 
			int fx = find(x), fy = find(y);
			if(fx != fy)
			{
				fa[fx] = fy;
				path[fy] = max(max(path[fy], path[fx]), (path[fx]+1)/2 + (path[fy]+1)/2 + 1);
			}
		}
	}
	return 0;
}
posted @ 2018-10-12 17:12  Misaka_Azusa  阅读(131)  评论(0编辑  收藏  举报
Live2D