[BZOJ2657][Zjoi2012]旅游(journey)(一些特殊的技巧+树的直径)
2018-03-24 21:51
344 查看
由于是三角剖分,所以可以把一个城市看作一个点,将相邻的城市对连边,形成一个n−2n−2个点的树,然后dfs求一遍树的直径,加11后就是答案。
而现在的关键在于怎样找出相邻的城市对。
首先找到三角剖分中所有的分界线。即对于每个三角形(城市)的三边,如果这条边不在多边形的边界上,那么这条边是分界线。
然后对于每条分界线,求出这条分界线两端的城市。
显然,这条分界线两端的三角形,一定包含有这条分界线作为三角形的某一边。
具体地,用一个map储存包含某一条边的三角形有哪些(包含同一条边的三角形最多22个)。
这样就能求出分界线两端的城市了。建树完毕。
代码:
而现在的关键在于怎样找出相邻的城市对。
首先找到三角剖分中所有的分界线。即对于每个三角形(城市)的三边,如果这条边不在多边形的边界上,那么这条边是分界线。
然后对于每条分界线,求出这条分界线两端的城市。
显然,这条分界线两端的三角形,一定包含有这条分界线作为三角形的某一边。
具体地,用一个map储存包含某一条边的三角形有哪些(包含同一条边的三角形最多22个)。
这样就能求出分界线两端的城市了。建树完毕。
代码:
#include <map> #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define For(i, a, b) for (i = a; i <= b; i++) using namespace std; inline int read() { int res = 0; bool bo = 0; char c; while (((c = getchar()) < '0' || c > '9') && c != '-'); if (c == '-') bo = 1; else res = c - 48; while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + (c - 48); return bo ? ~res + 1 : res; } typedef long long ll; const int N = 2e5 + 5, M = N * 3; int n, m, ecnt, nxt[M], adj , go[M], f , g , ans; map<ll, int> fir, sec; void add_edge(int u, int v) { nxt[++ecnt] = adj[u]; adj[u] = ecnt; go[ecnt] = v; nxt[++ecnt] = adj[v]; adj[v] = ecnt; go[ecnt] = u; } struct cyx { int u, v; cyx() {} cyx(int _u, int _v) : u(_u), v(_v) {} } edge[M]; bool comp(cyx a, cyx b) { if (a.u != b.u) return a.u < b.u; return a.v < b.v; } bool isnxt(int x, int y) { return x + 1 == y || (x == 1 && y == n); } ll prod(int u, int v) { return 1ll * u * (n - 1) + v; } void addsuf(int u, int v, int i) { ll id = prod(u, v); if (fir[id]) sec[id] = i; else fir[id] = i; } void dfs(int u, int fu) { for (int e = adj[u], v; e; e = nxt[e]) { if ((v = go[e]) == fu) continue; dfs(v, u); if (f[v] + 1 > f[u]) g[u] = f[u], f[u] = f[v] + 1; else if (f[v] + 1 > g[u]) g[u] = f[v] + 1; } } int main() { int i, x, y, z; n = read(); For (i, 1, n - 2) { x = read(); y = read(); z = read(); if (x > z) swap(x, z); if (y > z) swap(y, z); if (x > y) swap(x, y); if (!isnxt(x, y)) edge[++m] = cyx(x, y), addsuf(x, y, i); if (!isnxt(x, z)) edge[++m] = cyx(x, z), addsuf(x, z, i); if (!isnxt(y, z)) edge[++m] = cyx(y, z), addsuf(y, z, i); } sort(edge + 1, edge + m + 1, comp); For (i, 1, m) if (i == 1 || edge[i].u != edge[i - 1].u || edge[i].v != edge[i - 1].v) { ll id = prod(edge[i].u, edge[i].v); add_edge(fir[id], sec[id]); } dfs(1, 0); For (i, 1, n - 2) ans = max(ans, f[i] + g[i]); cout << ans + 1 << endl; return 0; }
相关文章推荐
- [BZOJ 2657][Zjoi2012]旅游(journey):树的直径
- BZOJ 2657 ZJOI 2012 旅游(journey) 树的直径
- bzoj 2657: [Zjoi2012]旅游(journey) (map建图+树的直径)
- [bzoj 2657] [Zjoi2012]旅游(journey)
- BZOJ 2657 (ZJOI 2012 旅游) 求树上最长链(树的直径) MAP建树+BFS/DFS
- BZOJ 2657 [Zjoi2012]旅游(journey)
- BZOJ 2657: [Zjoi2012]旅游(journey)
- bzoj2657: [Zjoi2012]旅游(journey)
- 【BZOJ】2657: [Zjoi2012]旅游(journey)
- BZOJ 2657 ZJOI2012 旅游(journey) 树形DP
- BZOJ2657: [Zjoi2012]旅游(journey)
- [bzoj2657][Zjoi2012]旅游 journey_ 对偶图_树形dp
- Bzoj2657 [Zjoi2012]旅游(journey)
- [BZOJ2657][Zjoi2012]旅游(journey)(dfs||树形dp)
- 【BZOJ 2657】 [Zjoi2012]旅游(journey)
- BZOJ 2657 [Zjoi2012] 旅游(journey)
- 【ZJOI2012】【BZOJ2657】旅游(journey)
- BZOJ2657:[ZJOI2012]旅游——题解
- [bzoj] 2657 ZJOI2012 旅游 || bfs
- BZOJ2657 [Zjoi2012]旅游(journey) 【树的直径】