zoukankan      html  css  js  c++  java
  • CF455C Civilization

    题目传送门

    这是一道双倍经验题 Luogu P2195
    虽然Luogu P2195的题意很迷,但确实是双倍经验


    先预处理出每棵树的直径,并用并查集维护哪些点在同一棵树里
    对于(1)操作,直接输出就可以了
    对于(2)操作,显然在两棵树直径的中点处连边最优。再用并查集维护一下即可

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define LL long long
    using namespace std;
    LL read() {
    	LL k = 0, f = 1; char c = getchar();
    	while(c < '0' || c > '9') {
    		if(c == '-') f = -1;
    		c = getchar();
    	}
    	while(c >= '0' && c <= '9')
    		k = k * 10 + c - 48, c = getchar();
    	return k * f;
    }
    struct zzz {
    	int t, nex;
    }e[300010 << 1]; int head[300010], tot;
    void add(int x, int y) {
    	e[++tot].t = y;
    	e[tot].nex = head[x];
    	head[x] = tot;
    }
    int fa[300010];
    int findd(int x) {
    	return fa[x] == x ? x : fa[x] = findd(fa[x]);
    }
    int que[300010], dis[300010], h, t;
    int dia[300010];
    void solve(int s) {
    	h = 1, t = 0; que[++t] = s; dis[s] = 1;
    	int maxn = -1, pos;
    	while(h <= t) {
    		int x = que[h++];
    		if(dis[x] > maxn) maxn = dis[x], pos = x;
    		for(int i = head[x]; i; i = e[i].nex) {
    			if(!dis[e[i].t])
    				que[++t] = e[i].t, dis[e[i].t] = dis[x] + 1;
    		}
    	}
    	for(int i = 1; i <= t; ++i) dis[que[i]] = 0;
    	h = 1, t = 0, que[++t] = pos; dis[pos] = 1;
    	maxn = -1;
    	while(h <= t) {
    		int x = que[h++];
    		if(dis[x] > maxn) maxn = dis[x];
    		for(int i = head[x]; i; i = e[i].nex) {
    			if(!dis[e[i].t])
    				que[++t] = e[i].t, dis[e[i].t] = dis[x] + 1;
    		}
    	}
    	int fx = findd(s);
    	dia[fx] = maxn-1;
    }
    int main() {
    	int n = read(), m = read(), q = read();
    	for(int i = 1; i <= n; ++i) fa[i] = i;
    	for(int i = 1; i <= m; ++i) {
    		int x = read(), y = read();
    		int fx = findd(x), fy = findd(y);
    		if(fx != fy) fa[fx] = fy;
    		add(x, y); add(y, x);
    	}
    	for(int i = 1; i <= n; ++i)
    		if(!dis[i]) solve(i);
    	for(int i = 1; i <= q; ++i) {
    		int opt = read(), x = read();
    		if(opt == 1) {
    			int fx = findd(x);
    			printf("%d
    ", dia[fx]);
    		}
    		else {
    			int y = read();
    			int fx = findd(x), fy = findd(y);
    			if(fx != fy) {
    				fa[fx] = fy;
    				dia[fy] = max((dia[fx]+1 >> 1) + (dia[fy]+1 >> 1) + 1, max(dia[fx], dia[fy]));
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    (Problem 14)Longest Collatz sequence
    (Problem 13)Large sum
    (Problem 10)Summation of primes
    (Problem 9)Special Pythagorean triplet
    (Problem 7)10001st prime
    (Problem 6)Sum square difference
    数组
    断点及复习
    抽象和封装
    类和对象
  • 原文地址:https://www.cnblogs.com/morslin/p/11855985.html
Copyright © 2011-2022 走看看