BZOJ2657: [Zjoi2012]旅游(journey) (树形DP)

题意:一个三角划分的凸多边形 画一条对角线 穿过最多的三角形

题解:把每一个三角形看作一个点 如果某条边是两个三角形的公共边 那么就把这两个三角形连边

   然后问题就转化为求树上的最长链了 就当求个直径就完了

#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
", zd);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/lwqq3/p/9180929.html