zoukankan      html  css  js  c++  java
  • 【树形DP】BZOJ1040-[ZJOI2008]骑士

    【题目大意】

    有n个骑士,给出他们的能力值和最痛恨的一位骑士。选出一个骑士军团,使得军团内没有矛盾的两人(不存在一个骑士与他最痛恨的人一同被选入骑士军团的情况),并且,使得这支骑士军团最具有战斗力,求战斗力的最大值。

    【思路】

    首先yy一下,可以知道这是一个基环森林。我们可以用以下方法:

    首先在每一棵基环树的环上任意找到一条边(用dfs来实现),记它的两个端点为u和v。然后删掉这条边(我这里用的方法是记录u,v在对方容器中的位置,并在后续操作中忽略这条边)。由于u和v不能同时取,在删掉u和v之间的边后存在以下两种情况:

    令g[i]为不取i时i及其子树的最大战斗力总和,f[i]则表示取i。

    (1)u不取,v任意。则以u为根进行树形DP,结果为g[u];

    (2)v不取,u任意。则以v为根进行树形DP,结果为g[v]。

    然后ans+max(g[u],g[v])。

    树形DP的过程非常地常规,就不赘述了 。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<vector>
      6 using namespace std;
      7 const int MAXN=1000000+500;
      8 typedef long long ll;
      9 vector<int> E[MAXN];
     10 int n,power[MAXN],hate[MAXN];
     11 int vis[MAXN];
     12 int U,V;
     13 ll g[MAXN],f[MAXN];
     14   
     15 void addedge(int u,int v)
     16 {
     17     E[u].push_back(v);
     18     E[v].push_back(u);
     19 }
     20   
     21 void dfs(int u,int fr)
     22 {
     23     vis[u]=1;
     24     for (int i=0;i<E[u].size();i++)
     25     {
     26         int to=E[u][i];
     27         if (to!=fr)
     28         {
     29             if (!vis[to]) dfs(to,u);
     30             else
     31             {
     32                 vis[to]=1;
     33                 U=u;V=to;
     34                 return;
     35             }
     36         }
     37     }
     38 }
     39   
     40 void TreeDP(int u,int fr,int rt,int ban)
     41 {
     42     vis[u]=1;
     43     f[u]=power[u];
     44     g[u]=0;
     45     for (int i=0;i<E[u].size();i++)
     46     {
     47         int to=E[u][i];
     48         if (u==rt && i==ban) continue;
     49         if (to!=fr && to!=rt)
     50         {
     51             TreeDP(to,u,rt,ban);
     52             f[u]+=g[to];
     53             g[u]+=max(g[to],f[to]);
     54         }
     55     }
     56 }
     57   
     58 void init()
     59 {
     60     scanf("%d",&n);
     61     for (int i=1;i<=n;i++)
     62     {
     63         scanf("%d%d",&power[i],&hate[i]);
     64         addedge(i,hate[i]);
     65     }
     66 } 
     67   
     68 void get_ans()
     69 {
     70     memset(vis,0,sizeof(vis));
     71     ll ans=0;
     72     for (int i=1;i<=n;i++)
     73         if (!vis[i]) 
     74         {
     75             dfs(i,-1);
     76             int banu,banv;
     77             for (int i=0;i<E[U].size();i++) if (E[U][i]==V)
     78             {
     79                 banu=i;
     80                 break;
     81             }
     82             for (int i=0;i<E[V].size();i++) if (E[V][i]==U)
     83             {
     84                 banv=i;
     85                 break;
     86             }
     87              
     88  
     89             TreeDP(U,-1,U,banu);
     90             ll uans=g[U];
     91               
     92             TreeDP(V,-1,V,banv);
     93             ll vans=g[V];
     94             ans+=max(uans,vans);
     95         }
     96     cout<<ans<<endl;
     97 }
     98   
     99 int main()
    100 {
    101     init();
    102     get_ans();
    103     return 0;   
    104 }
  • 相关阅读:
    最简单的jQuery插件
    SQL执行时间
    Resharper 8.2 注册码
    Module模式
    RestSharp使用
    使用MVC过滤器保存操作日志
    Ajax Post 类实例
    IBatis分页显示
    IBatis插入类的实例
    Topcoder SRM629 DIV2 解题报告
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/6057641.html
Copyright © 2011-2022 走看看