BZOJ2657: [Zjoi2012]旅游(journey) (树形DP)
题意:一个三角划分的凸多边形 画一条对角线 穿过最多的三角形
题解:把每一个三角形看作一个点 如果某条边是两个三角形的公共边 那么就把这两个三角形连边
然后问题就转化为求树上的最长链了 就当求个直径就完了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> #include <algorithm> #include <iostream> using namespace std; struct node { int x, y, id; }E[600005]; bool cmp(node A, node B) { if(A.x == B.x) return A.y < B.y; else return A.x < B.x; } int n, zd, rt; int to[400005]; int dis[200005]; int nex[400005]; int head[200005]; void dfs(int x, int fa) { int c = head[x]; for(int i = c; i; i = nex[i]) { int v = to[i]; if(v == fa) continue; dis[v] = dis[x] + 1; if(dis[v] > zd) rt = v, zd = dis[v]; dfs(v, x); } } int main() { zd = rt = 0; scanf("%d", &n); int cnt = 0; for(int i = 1; i <= n - 2; i++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); if(a < b) swap(a, b); if(b < c) swap(b, c); if(a < b) swap(a, b); E[++cnt].x = a; E[cnt].y = b; E[cnt].id = i; E[++cnt].x = b; E[cnt].y = c; E[cnt].id = i; E[++cnt].x = a; E[cnt].y = c; E[cnt].id = i; } sort(E + 1, E + 1 + cnt, cmp); int cn = 0; for(int i = 2; i <= cnt; i++) { if(E[i].x == E[i - 1].x && E[i].y == E[i - 1].y) { int u = E[i].id; int v = E[i - 1].id; to[++cn] = u; nex[cn] = head[v]; head[v] = cn; to[++cn] = v; nex[cn] = head[u]; head[u] = cn; } } dfs(1, -1); zd = 0; int l = rt; dis[rt] = 1; dfs(rt, -1); printf("%d\n", zd); return 0; }