题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4126

$LRJ$紫书例题$9-26$

题目大意:

给定一颗树 有些边已经标好方向 现在要给其余的边标上方向 使得最长的有向链最短

$HIT:$ 题目额外给了一个结论 假设已经确定方向的边所能得到的最长链为$k$ 最后的最长链一定$k$ 或$k + 1$

不知道是自己太久没有写树形$DP$还是这题的确比较麻烦 花了好久才折腾出来

首先 利用题目给的结论 我们实际上只需要解决以下这个几乎等价的问题

判断所给的树是否可以构造出最长链不超过$k$的方案

如果是的 那么最长链就是$k$否则为$k + 1$


对于这个可行解问题 我们可以这样考虑

对于每颗子树的最长链 它要么经过这颗子树的根节点 要么在这个根节点的某个儿子所对应的子树中

因此只需递归地去检验每颗子树是否合法即可

我们可以建立三个数组 $f[x][y]$ $up[x]$ $down[x]$

$f[x][y]$代表 到达该根节点$x$的向上的最长链最小值为$y$时向下的最长链最小值为多少

$up[x]$ $down[x]$分别代表该根节点向上/下的最长链的最小值

然后由于数据范围比较小 所以可以直接用这种$O(n^2)$的方法轻松解决

 #include <bits/stdc++.h>
using namespace std;
const int N = , E = N << ;
int firste[N], nexte[E], v[E], w[E];
int n, e, ans;
void build(int x, int y, int z)
{
nexte[++e] = firste[x];
firste[x] = e;
v[e] = y;
w[e] = z;
}
void init(int uu)
{
int vv;
char ch;
n = ;
e = ;
memset(firste, , sizeof firste);
ans = ;
do
{
n = max(n, uu);
while(scanf("%d%c", &vv, &ch), vv)
{
n = max(n, vv);
if(ch == 'd')
{
build(uu, vv, );
build(vv, uu, );
}
else if(ch == 'u')
{
build(uu, vv, );
build(vv, uu, );
}
else
{
build(uu, vv, );
build(vv, uu, );
}
}
}while(scanf("%d", &uu), uu);
}
void dfs0(int u, int fa, int dist)
{
ans = max(ans, dist);
for(int p = firste[u]; p; p = nexte[p])
if(w[p] && v[p] != fa)
dfs0(v[p], u, dist + );
}
int f[N][N], up[N], down[N];
bool dfs(int u, int fa)
{
for(int p = firste[u]; p; p = nexte[p])
if(v[p] != fa)
{
if(!dfs(v[p], u))
return ;
if(w[p])
{
for(int i = ; i <= min(down[v[p]], ans); ++i)
f[u][i] = ans + ;
}
else if(w[p ^ ])
{
for(int i = ; i <= ans; ++i)
f[u][i] = max(f[u][i], up[v[p]] + );
}
else
{
for(int i = ; i <= down[v[p]]; ++i)
f[u][i] = max(f[u][i], up[v[p]] + );
}
}
bool re = ;
for(int i = ; i <= ans; ++i)
if(f[u][i] + i <= ans)
{
re = ;
down[u] = min(down[u], i);
up[u] = min(up[u], f[u][i]);
}
return re;
}
int main()
{
int tmp;
while(scanf("%d", &tmp), tmp)
{
init(tmp);
for(int i = ; i <= n; ++i)
dfs0(i, i, );
memset(f, , sizeof f);
memset(down, 0x3f, sizeof down);
memset(up, 0x3f, sizeof up);
if(dfs(, ))
printf("%d\n", ans + );
else
printf("%d\n", ans + );
}
return ;
}

UVA 1380 A Scheduling Problem的更多相关文章

  1. 【暑假】[深入动态规划]UVa 1380 A Scheduling Problem

     UVa 1380 A Scheduling Problem 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=41557 ...

  2. 【UVA 1380】 A Scheduling Problem (树形DP)

    A Scheduling Problem   Description There is a set of jobs, say x1, x2,..., xn <tex2html_verbatim_ ...

  3. UVa 101 The Blocks Problem Vector基本操作

    UVa 101 The Blocks Problem 一道纯模拟题 The Problem The problem is to parse a series of commands that inst ...

  4. UVA - 524 Prime Ring Problem(dfs回溯法)

    UVA - 524 Prime Ring Problem Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & % ...

  5. uva 10837 - A Research Problem(欧拉功能+暴力)

    题目链接:uva 10837 - A Research Problem 题目大意:给定一个phin.要求一个最小的n.欧拉函数n等于phin 解题思路:欧拉函数性质有,p为素数的话有phip=p−1; ...

  6. UVA 810 - A Dicey Problem(BFS)

    UVA 810 - A Dicey Problem 题目链接 题意:一个骰子,给你顶面和前面.在一个起点,每次能移动到周围4格,为-1,或顶面和该位置数字一样,那么问题来了,骰子能不能走一圈回到原地, ...

  7. UVA 10026 Shoemaker's Problem 鞋匠的难题 贪心+排序

    题意:鞋匠一口气接到了不少生意,但是做鞋需要时间,鞋匠只能一双一双地做,根据协议每笔生意如果拖延了要罚钱. 给出每笔生意需要的天数和每天的罚钱数,求出最小罚钱的排列顺序. 只要按罚款/天数去从大到小排 ...

  8. UVA 1640 The Counting Problem UVA1640 求[a,b]或者[b,a]区间内0~9在里面各个数的数位上出现的总次数。

    /** 题目:UVA 1640 The Counting Problem UVA1640 链接:https://vjudge.net/problem/UVA-1640 题意:求[a,b]或者[b,a] ...

  9. Uva 101 -- the block problem

    Uva 101 the block problem 题目大意: 输入n,得到编号为0~n-1的木块,分别摆放在顺序排列编号为0~n-1的位置.现对这些木块进行操作,操作分为四种. 1.move a o ...

随机推荐

  1. tarjan算法应用 割点 桥 双连通分量

    tarjan算法的应用. 还需多练习--.遇上题目还是容易傻住 对于tarjan算法中使用到的Dfn和Low数组. low[u]:=min(low[u],dfn[v])--(u,v)为后向边,v不是u ...

  2. [BZOJ 3456]城市规划(cdq分治+FFT)

    [BZOJ 3456]城市规划(cdq分治+FFT) 题面 求有标号n个点无向连通图数目. 分析 设\(f(i)\)表示\(i\)个点组成的无向连通图数量,\(g(i)\)表示\(i\)个点的图的数量 ...

  3. 基于gulp的前端自动化方案

    前言 ​ 最近几年前端技术发展日新月异,特别是单页应用的普及.组件化.工程化.自动化成了前端发展的趋势.webpack已经成为了前端打包构建的主流,但是一些老古董的项目还是存在的,也有优化的必要,正好 ...

  4. 洛谷 - P1522 - 牛的旅行 - Cow Tours - Floyd

    https://www.luogu.org/problem/P1522 好坑啊,居然还有直径不通过新边的数据,还好不是很多. 注意一定要等Floyd跑完之后再去找连通块的直径,不然一定是INF. #i ...

  5. js随机验证码

    随机验证码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <ti ...

  6. Ubuntu 增加新用户并赋予root权限及免密的方法

    添加用户 添加一个名为hylink的用户 adduser hylink 修改密码 passwd hylink Changing password for user hylink. New UNIX p ...

  7. nsswitch.conf - 系统数据库及名字服务开关配置文件

    DESCRIPTION C 程序库里很多函数都需要配置以便能在本地环境正常工作, 习惯上是使用文件(例如`/etc/passwd') 来完成这一任务. 但别的名字服务, 如网络信息服务NIS, 还有域 ...

  8. JavaEE高级-MyBatis学习笔记

    一.MyBatis简介 - MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架. - MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集. - My ...

  9. SVN本地搭建服务

    本地搭建svn 服务端并使用 1.下载SVN服务端软  VisualSVN server 地址:http://subversion.apache.org/packages.html 2.安装 Visu ...

  10. CIC许可更新

    打开IA软件,点击软件中的[License],可以查看当前许可是否可用或者过期,如果过期,点击下方的[Load License],选择最新的I3许可文件加载,重启电脑.