zoukankan      html  css  js  c++  java
  • BZOJ1040: [ZJOI2008]骑士 树套环DP

    • 题意:一个图n个点n条边保证点能互相到达,ab有边意味着ab互相厌恶,求一个集合,使得集合里元素最多而且没有人互相厌恶
    • 删去环上一条边树形dp,比如删掉的边连着a,b,那么先dp出不选a的最大值,再dp出不选b的最大值。
    • 如果每次找到环删边的方法是直接把边断掉,这样会出现一个Bug就是a有指向b的边,b有指向a的边,这样形成的环其实不需要删掉
    • 解决办法:就是建边的时候如果是上面的情况a b之间就建了两条边,那这样把重边删去就行了(删完之后就break掉)
    • 代码:
       1 #include <bits/stdc++.h>
       2 #define nmax 1000010
       3   
       4 using namespace std;
       5 typedef long long ll;
       6 vector <int> g[nmax];
       7 int n, in, a, b, cnt;
       8 ll d[nmax][2]={0}; // dp[u][1] = sum dp[v][0] + zl[u]   dp[u][0] = sum max(dp[v][0],dp[v][1]+x[v]) 
       9 int zl[nmax], vis[nmax]={0};
      10   
      11 void dfs(int u, int fa){
      12     d[u][1] = zl[u];
      13     for (int i=0; i<g[u].size(); i++) {
      14         int v = g[u][i];
      15         if(v==fa || v==0) continue;
      16         dfs(v, u);
      17         d[u][1] += d[v][0];
      18         d[u][0] += max(d[v][0], d[v][1]);
      19     }
      20 }
      21   
      22 void fr(int u, int fa){
      23     cnt++;
      24     vis[u] = 1;
      25     for (int i=0; i<g[u].size(); i++) {
      26         int v = g[u][i];
      27         if(v == fa || v == 0) continue;
      28         if( vis[v] ) { a=u; b=v; }
      29         else fr(v, u);
      30     }
      31 }
      32   
      33 inline void del(int x, int y){
      34     for (int i=0; i<g[x].size(); i++) if( g[x][i] == y ) { g[x][i] = 0; break; }
      35 }
      36   
      37 inline void init(int u, int fa){
      38     d[u][0] = d[u][1] = 0;
      39     for (int i=0; i<g[u].size(); i++) {
      40         int v = g[u][i];
      41         if( v==fa || v==0 ) continue;
      42         init(v, u);
      43     }
      44 }
      45   
      46 int main(){
      47     cin >> n;
      48     for (int i=1; i<=n; i++) {
      49         scanf("%d%d", &zl[i], &in);
      50         g[in].push_back(i);
      51         g[i].push_back(in);
      52     }
      53     ll ans=0, ta;
      54     for (int i=1; i<=n; i++) {
      55         if(vis[i]) continue;
      56         cnt = 0; //这个树套环的节点个数
      57         fr(i, 0);
      58         del(a, b);
      59         del(b, a);
      60         dfs(a, 0);
      61         ta = d[a][0];
      62         init(i, 0);
      63         dfs(b, 0);
      64         ta = max(ta, d[b][0] );
      65         init(i, 0);
      66         ans += ta;
      67     }
      68     cout << ans << endl;
      69     return 0;
      70 }
      (⓿_⓿)
  • 相关阅读:
    Python文件File方法
    python的slice notation的特殊用法
    函数
    字典
    python 笔记7
    列表解析与生成器
    [CenOS7][Mac] MAC环境中dubbo连接zookeeper超时
    [JAVA][Thread] 实现Runnable接口和继承Thread类创建线程哪种方式更好?
    [Java] String字符常量类型作为参数传递的一些问题
    [JAVA]hashCode()和identityHashCode()的区别
  • 原文地址:https://www.cnblogs.com/jiecaoer/p/11839166.html
Copyright © 2011-2022 走看看