【树的直径+并查集】 codeforces 455C - Civilization
2014-08-10 14:32
369 查看
先预处理出每个集合的最长路,就是树的直径,可以两次BFS找。。然后合并集合更新最长路就是在dep[a],dep[b],(dep[a]+1)/2+(dep[b]+1)/2+1三者取最大。。
#include <iostream> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <algorithm> #include <cstring> #include <climits> #include <cstdlib> #include <cmath> #include <time.h> #define maxn 300005 #define maxm 100005 #define eps 1e-10 #define mod 3 #define INF 1e9 #define lowbit(x) (x&(-x)) #define ls o<<1 #define rs o<<1 | 1 #define lson o<<1, L, mid #define rson o<<1 | 1, mid+1, R typedef long long LL; //typedef int LL; using namespace std; int n, m; int f[maxn], dep[maxn]; vector<int> vec[maxn]; vector<int> g[maxn]; set<int> s[maxn]; queue<int> q; int vis[maxn]; int dis[maxn]; int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); } void debug(void) { for(int i = 1; i <= n; i++) printf("AA %d BB\n", dep[i]); } int bfs(int u) { int d = g[f[u]].size(), mx; for(int i = 0; i < d; i++) dis[g[f[u]][i]] = INF; q.push(u), dis[u] = 0, mx = u; while(!q.empty()) { int x = q.front(); q.pop(); int d = vec[x].size(); for(int i = 0; i < d; i++) { if(dis[vec[x][i]] > dis[x] + 1) { dis[vec[x][i]] = dis[x] + 1; q.push(vec[x][i]); if(dis[vec[x][i]] > dis[mx]) mx = vec[x][i]; } } } return mx; } void init(void) { int q, u, v, aa, bb; scanf("%d%d%d", &n, &m, &q); for(int i = 0; i <= n; i++) f[i] = i; while(m--) { scanf("%d%d", &u, &v); vec[u].push_back(v); vec[v].push_back(u); aa = find(u); bb = find(v); if(aa == bb) continue; else if(aa < bb) f[bb] = aa; else f[aa] = bb; } m = q; for(int i = 1; i <= n; i++) find(i); for(int i = 1; i <= n; i++) { s[f[i]].insert(i); g[f[i]].push_back(i); } for(int i = 1; i <= n; i++) { if(f[i] == i) { int tmp = bfs(i); tmp = bfs(tmp); dep[i] = dis[tmp]; } } } void work(void) { int k, a, b, aa, bb; while(m--) { scanf("%d", &k); if(k == 1) { scanf("%d", &a); aa = find(a); printf("%d\n", dep[aa]); } else { scanf("%d%d", &a, &b); aa = find(a); bb = find(b); if(aa == bb) continue; int tmp = (dep[aa] + 1)/2 + (dep[bb] + 1)/2 + 1; tmp = max(tmp, max(dep[aa], dep[bb])); if(aa > bb) f[aa] = bb, dep[bb] = tmp; else f[bb] = aa, dep[aa] = tmp; } } } int main(void) { init(); work(); return 0; }
相关文章推荐
- Codeforces 455C —— Civilization(并查集,树上最长链)
- codeforces 455C C. Civilization(树形dp+树的直径+并查集)
- Civilization CodeForces - 455C (并查集+树的直径+推公式 +链式前向星存储边)
- 【打CF,学算法——四星级】CodeForces 455C Civilization (【详解】并查集+树的直径)
- Codeforces 455C. Civilization (树的直径+并查集)
- Codeforces Round #260 (Div. 1) C. Civilization 并查集,直径
- Codeforces 455C Civilization 树的直径+并查集
- codeforces 455C Civilization
- codeforces 455C 并查集
- Codeforces 734E Anton and Tree【并查集缩点||DFS缩点+树的直径】
- CodeForces 455C-Civilization
- Codeforces 455E Civilization【思维+树的直径+并查集】
- CodeForces - 445B_DZY Loves Chemistry_并查集
- codeforces 593 D. Happy Tree Party (LCA + 并查集)
- codeforces 14D 树的直径
- Codeforces 217A. Ice Skating 【并查集】
- poj 3310(并查集判环,图的连通性,树上最长直径路径标记)
- Codeforces 396 div.2 带权并查集
- CodeForces - 505B Mr. Kitayuta's Colorful Graph(二维并查集)
- HDU 4514 - 湫湫系列故事——设计风景线 (并查集判圈 树的直径)