• UVA 1380 A Scheduling Problem


    题目链接: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)$的方法轻松解决

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 const int N = 210, E = N << 1;
      4 int firste[N], nexte[E], v[E], w[E];
      5 int n, e, ans;
      6 void build(int x, int y, int z)
      7 {
      8     nexte[++e] = firste[x];
      9     firste[x] = e;
     10     v[e] = y;
     11     w[e] = z;
     12 }
     13 void init(int uu)
     14 {
     15     int vv;
     16     char ch;
     17     n = 0;
     18     e = 1;
     19     memset(firste, 0, sizeof firste);
     20     ans = 0;
     21     do
     22     {
     23         n = max(n, uu);
     24         while(scanf("%d%c", &vv, &ch), vv)
     25         {
     26             n = max(n, vv);
     27             if(ch == 'd')
     28             {
     29                 build(uu, vv, 1);
     30                 build(vv, uu, 0);
     31             }
     32             else if(ch == 'u')
     33             {
     34                 build(uu, vv, 0);
     35                 build(vv, uu, 1);
     36             }
     37             else
     38             {
     39                 build(uu, vv, 0);
     40                 build(vv, uu, 0);
     41             }
     42         }
     43     }while(scanf("%d", &uu), uu);
     44 }
     45 void dfs0(int u, int fa, int dist)
     46 {
     47     ans = max(ans, dist);
     48     for(int p = firste[u]; p; p = nexte[p])
     49         if(w[p] && v[p] != fa)
     50             dfs0(v[p], u, dist + 1);
     51 }
     52 int f[N][N], up[N], down[N];
     53 bool dfs(int u, int fa)
     54 {
     55     for(int p = firste[u]; p; p = nexte[p])
     56         if(v[p] != fa)
     57         {
     58             if(!dfs(v[p], u))
     59                 return 0;
     60             if(w[p])
     61             {
     62                 for(int i = 0; i <= min(down[v[p]], ans); ++i)
     63                     f[u][i] = ans + 1;
     64             }
     65             else if(w[p ^ 1])
     66             {
     67                 for(int i = 0; i <= ans; ++i)
     68                     f[u][i] = max(f[u][i], up[v[p]] + 1);
     69             }
     70             else
     71             {
     72                 for(int i = 0; i <= down[v[p]]; ++i)
     73                     f[u][i] = max(f[u][i], up[v[p]] + 1);
     74             }
     75         }
     76     bool re = 0;
     77     for(int i = 0; i <= ans; ++i)
     78         if(f[u][i] + i <= ans)
     79         {
     80             re = 1;
     81             down[u] = min(down[u], i);
     82             up[u] = min(up[u], f[u][i]);
     83         }
     84     return re;
     85 }
     86 int main()
     87 {
     88     int tmp;
     89     while(scanf("%d", &tmp), tmp)
     90     {
     91         init(tmp);
     92         for(int i = 1; i <= n; ++i)
     93                 dfs0(i, i, 0);
     94         memset(f, 0, sizeof f);
     95         memset(down, 0x3f, sizeof down);
     96         memset(up, 0x3f, sizeof up);
     97         if(dfs(1, 1))
     98             printf("%d
    ", ans + 1);
     99         else
    100             printf("%d
    ", ans + 2);
    101     }
    102     return 0;
    103 }
  • 相关阅读:
    Sumdiv POJ
    Tallest Cow POJ
    P2280 [HNOI2003]激光炸弹(二维前缀和)
    Strange Towers of Hanoi POJ
    Manjaro (KDE)安装踩坑记录
    Petya and Array CodeForces
    CodeForces
    Philosopher’s Walk(递归)
    2018 icpc 青岛网络赛 J.Press the Button
    POJ 1003: Hangover
  • 原文地址:https://www.cnblogs.com/sagitta/p/6142796.html
Copyright © 2020-2023  润新知