(树形DP) bzoj 2657

2657: [Zjoi2012]旅游(journey)

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 604  Solved: 387
[Submit][Status][Discuss]

Description

到了难得的暑假,为了庆祝小白在数学考试中取得的优异成绩,小蓝决定带小白出去旅游~~

经过一番抉择,两人决定将T国作为他们的目的地。T国的国土可以用一个凸N边形来表示,N个顶点表示N个入境/出境口。T国包含N-2个城市,每个城市都是顶点均为N边形顶点的三角形(换而言之,城市组成了关于T国的一个三角剖分)。两人的旅游路线可以看做是连接N个顶点中不相邻两点的线段。

为了能够买到最好的纪念品,小白希望旅游路线上经过的城市尽量多。作为小蓝的好友,你能帮帮小蓝吗?

Input

每个输入文件中仅包含一个测试数据。

第一行包含两个由空格隔开的正整数N,N的含义如题目所述。

接下来有N-2行,每行包含三个整数 p,q,r,表示该城市三角形的三个顶点的编号(T国的N个顶点按顺时间方向从1至n编号)。

Output

输出文件共包含1行,表示最多经过的城市数目。(一个城市被当做经过当且仅当其与线路有至少两个公共点)

Sample Input

6
1 2 4
2 3 4
1 4 5
1 5 6

Sample Output

4

HINT

4<=N<=200000

Source

巧妙的建图+树的直径~

有n-2个三角形,他们中间用n-3条边隔开,我们把三角形看作点,有公共边的三角形连边,就构成一棵树了!

因为树上两个点之间的边与图中两个三角形的公共边一一对应,因此在树上走一条边相当于在图中走一条公共边,;

而走一条公共边两个三角形都经过两次了,表示到达了两个城市。

所以问题就变成了求树的最长链即树的直径。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
map<pair<int,int>,int> mp;
int n,dp[200005],siz[200005];
vector<int> e[200005];
int a[4],ans;
void build(int pos,int x,int y)
{
    int st;
    st=mp[make_pair(x,y)];
    if(st)
    {
        e[st].push_back(pos);
        e[pos].push_back(st);
    }
    else
        mp[make_pair(x,y)]=pos;
}
void dfs(int u,int father)
{
    siz[u]=1;
    for(int i=0;i<e[u].size();i++)
    {
        int v=e[u][i];
        if(v==father)
            continue;
        dfs(v,u);
        ans=max(ans,siz[u]+siz[v]);
        siz[u]=max(siz[u],siz[v]+1);
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n-2;i++)
    {
        scanf("%d%d%d",&a[1],&a[2],&a[3]);
        sort(a+1,a+1+3);
        build(i,a[1],a[2]);
        build(i,a[2],a[3]);
        build(i,a[1],a[3]);
    }
    dfs(1,-1);
    printf("%d\n",ans);
    return 0;
}

  

时间: 2024-10-10 10:28:31

(树形DP) bzoj 2657的相关文章

(树形DP) bzoj 4033

4033: [HAOI2015]T1 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 120  Solved: 57[Submit][Status][Discuss] Description 有一棵点数为 N 的树,树边有边权.给你一个在 0~ N 之内的正整 数 K ,你要在这棵树中选择 K个点,将其染成黑色,并将其他 的 N-K个点染成白色 . 将所有点染色后,你会获得黑点两两之间的距 离加上白点两两之间的距离的和的受益.问受益最大值是多少.

BZOJ 1093 最大半连通子图(强连通分量+树形DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1093 题意: 思路:(1)首先,强连通分量中的一个点若在最大半连通子图中,则必定整个连通分量中的点都在,因为都在还是满足半连通的性质而且使得节点数更多. (2)因此,求出强连通分量缩点,形成一个有向无环图,其实与树是差不多的.在这个图上DP一次即可,也就是找出最长链以及最长链的个数. vector<int> g[N],g1[N]; int n,m,mod; int dfn[N],lo

BZOJ 1924 所驼门王的宝藏(强连通分量+树形DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1924 题意: 思路:首先建立所有可达点之间的有向图.之后求强连通分量SCC,缩点重新构图.然后就是一个树,树形DP一下即可. int n,r,c; map<i64,int> mp; map<int,int> mp1,mp2; struct node { int x,y,op; }; node a[N]; int visit[N]; vector<int> V1

[BZOJ 4033] [HAOI2015] T1 【树形DP】

题目链接:BZOJ - 4033 题目分析 使用树形DP,用 f[i][j] 表示在以 i 为根的子树,有 j 个黑点的最大权值. 这个权值指的是,这个子树内部的点对间距离的贡献,以及 i 和 Father[i] 之间的边对答案的贡献(比如这条边对黑点对距离和的贡献就是子树内部的黑点数 * 子树外部的黑点数 * 这条边的权值). 然后DFS来求,枚举 i 的每个儿子 j,现在的 f[i][] 是包含了 [1, j-1] 子树,然后两重循环枚举范围是 [1, j - 1] 的子树总 Size 和

bzoj 3566: [SHOI2014]概率充电器 树形DP

首先普及一个概率公式 P(A+B)=P(A)+P(B)-P(AB) 题意:一些充电元件和导线构成一棵树,充电元件是否能充电有2种情况, 1.它自己有qi%的概率充电 2.与它相邻的元件通过导线给它充电(导线有p%的概率导通) 求最终充了电的元件的期望 题解:首先可以将元件能否充电分成3种情况考虑, 1.它自己给自己充好了电 2.它的儿子方向给它传送了电 3.它的父亲方向给它传送了电. 对于1,题目已经给出可以直接赋值, 对于2,可以通过一次树的深度遍历求得.pson[now]=pson[now]

BZOJ 2878([Noi2012]迷失游乐园-树形DP+环加外向树+期望DP+vector的erase)

2878: [Noi2012]迷失游乐园 Time Limit: 10 Sec  Memory Limit: 512 MBSec  Special Judge Submit: 319  Solved: 223 [Submit][Status] Description 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩.进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环(即m只可能等于n或者n-1).小Z现在所在的大门也正好是

BZOJ 2878: [Noi2012]迷失游乐园( 树形dp )

一棵树的话直接树形dp(求出往下走和往上走的期望长度). 假如是环套树, 环上的每棵树自己做一遍树形dp, 然后暴力枚举(环上的点<=20)环上每个点跑经过环上的路径就OK了. --------------------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm&

BZOJ 2435 道路修建 NOI2011 树形DP

一看到这道题觉得很水,打了递归树形DP后RE了一组,后来发现必须非递归(BFS) 递归版本84分: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int N,point[1000003],next[2000003],v[2000003],c[2000003],cnt=0,f[1000003]; bool p[1000003]; long long sum=0; vo

BZOJ 2314: 士兵的放置( 树形dp )

树形dp... dp(x, 0)表示结点x不放士兵, 由父亲控制: dp(x, 1)表示结点x不放士兵, 由儿子控制: dp(x, 2)表示结点x放士兵. ------------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> using namespace st