• BZOJ 1040 ZJOI 2008 骑士 树形DP


    题意:

    有一些战士,他们有战斗力和讨厌的人,选择一些战士,使他们互不讨厌,且战斗力最大,范围1e6

    分析:

    把战士看作点,讨厌的关系看作一条边,连出来的是一个基环树森林。

    对于一棵基环树,我们找出环,选择环上一条边(u,v)。

    那么只需考虑两种情况:1、u不选,v任意;2、v不选,u任意。答案取max累计即可

    程序:

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <string>
     5 #include <algorithm>
     6 #include <iostream>
     7 
     8 using namespace std;
     9 
    10 #define REP(i, a, b) for (int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
    11 #define mset(a, b) memset(a, b, sizeof(a))
    12 #define max_(a, b) a > b ? a : b
    13 const int maxn = 1e6+10;
    14 typedef long long LL;
    15 int n;
    16 struct Edge
    17 {
    18     int v, nxt;
    19     Edge (int v = 0, int nxt = 0):
    20         v(v), nxt(nxt) {}
    21 }e[maxn*2];
    22 int head[maxn], label;
    23 int U, V, E, w[maxn];
    24 bool vis[maxn];
    25 LL f[maxn][2];
    26 
    27 template <class TAT>
    28 void Ckmax(TAT &a, const TAT &b)
    29 {
    30     if (a < b) a = b;
    31 }
    32 
    33 void ins(int u, int v)
    34 {
    35     e[++label] = Edge(v, head[u]), head[u] = label;
    36     e[++label] = Edge(u, head[v]), head[v] = label;
    37 }
    38 
    39 void dfs(int u, int fa)
    40 {
    41     for (int i = head[u]; i != -1; i = e[i].nxt)
    42     {
    43         int v = e[i].v;
    44         if (v == fa) continue ;
    45         if (vis[v])
    46         {
    47             U = u, V = v, E = i;
    48             continue ;
    49         }
    50         vis[v] = true;
    51         dfs(v, u);
    52     }
    53 }
    54 
    55 void work(int u, int fa, int ban)
    56 {
    57     f[u][0] = 0, f[u][1] = w[u];
    58     for (int i = head[u]; i != -1; i = e[i].nxt)
    59     {
    60         int v = e[i].v;
    61         if (v == fa || i == ban || i == (ban^1)) continue ;
    62         work(v, u, ban);
    63         f[u][0] += max_(f[v][0], f[v][1]);
    64         f[u][1] += f[v][0];
    65     }
    66 }
    67 
    68 int main()
    69 {
    70     scanf("%d", &n);
    71     REP(i, 1, n) head[i] = -1;
    72     label = -1;
    73     REP(i, 1, n)
    74     {
    75         int v;
    76         scanf("%d %d", &w[i], &v);
    77         ins(i, v);
    78     }
    79     mset(vis, 0), mset(f, 0);
    80     LL ans = 0;
    81     REP(i, 1, n)
    82         if (!vis[i])
    83         {
    84             vis[i] = true, dfs(i, 0);
    85             LL temp;
    86             work(U, 0, E);
    87             temp = f[U][0];
    88             work(V, 0, E);
    89             Ckmax(temp, f[V][0]);
    90             ans += temp;
    91         }
    92     printf("%lld
    ", ans);
    93     return 0;
    94 }
    View Code
  • 相关阅读:
    if 语句运用
    c#语言基础
    关于条件运算符的应用
    Could not open Hibernate Session for transaction;
    node to traverse cannot be null!
    Struts2文件下载中文名乱码
    Spring MVC框架下的第一个Hello World程序
    strtus2中的defaultactionref无效的解决方法
    c 笔记
    工具系列1
  • 原文地址:https://www.cnblogs.com/-ZZB-/p/6586629.html
Copyright © 2020-2023  润新知