zoukankan      html  css  js  c++  java
  • [BZOJ1040][P2607][ZJOI2008]骑士[树形DP+基环树]

    做法跟没有上司的舞会差不多,只要把环上的任两点之间断开,从断开的两点分别为起点跑一次树形dp,然后取max就行了

    几个坑点:

    1.可能有多个连通块,每个连通块都是一个基环树

    2.断环的时候没想到什么方法。。。后来用vector暴力找的。。。

    3.爆int

    4.代码里有个小地方,加了注释

    常数极大,不加fread luogu会TLE一个点

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 1e6+7;
    vector<int>G[MAXN]; bool vis[MAXN]; int x, y;
    char buf[15<<20], *p1 = buf;
    #define getchar() (*p1++)
    inline void read(int &x) {
      register int c = getchar(), f = 1; x = 0;
      while(!isdigit(c)) (c=='-')&&(f=-1), c = getchar();
      while(isdigit(c)) x = x * 10 + c - '0', c = getchar();
      x *= f;
    }
    inline void add(int u, int v) {
      G[u].push_back(v), G[v].push_back(u);
    }
    int v[MAXN], n, m;
    long long dp[MAXN][2];
    void get(int u, int fa=0) {
      if (vis[u]) return x = u, y = fa, void();
      vis[u] = 1;
      for(vector<int>::iterator it = G[u].begin(); it != G[u].end(); ++it) {
        if (*it == fa) continue;
        get(*it, u);
      }
    } 
    void treedp(int u, int fa=0) {
      if (!u) return ;
      dp[u][1] = v[u], dp[u][0] = 0;
      for(vector<int>::iterator it = G[u].begin(); it != G[u].end(); ++it) {
        if (*it == fa) continue;
        treedp(*it, u);
        dp[u][0] += max(dp[*it][0], dp[*it][1]);
        dp[u][1] += dp[*it][0];   
      }
    }
    int main(void) {
      fread(buf, 1, 15<<20, stdin);
      read(n);
      for(int to, i = 1; i <= n; ++i) {
        read(v[i]), read(to);
        add(i, to);
      }
      long long Ans = 0;
      for(int i = 1; i <= n; ++i) {
        if (vis[i]) continue;
        get(i);
        for(int j = 0; j < G[x].size(); ++j) 
          if (G[x][j] == y) {G[x][j] = 0; break;}
        for(int j = 0; j < G[y].size(); ++j) 
          if (G[y][j] == x) {G[y][j] = 0; break;}
        treedp(x);
        long long tmp = dp[x][0];//必须存起来,不然treedp[y]的时候dp[x][0]就变了
        treedp(y);
        Ans += max(tmp, dp[y][0]);
      }
      cout << Ans;
      return 0;
    }
    
  • 相关阅读:
    并查集模板
    143. 最大异或对(Trie树存整数+二进制)
    Trie树模板
    835. 字符串统计(Trie树模板题)
    生兔兔
    汉诺塔问题
    一本通 1296:开餐馆
    一本通 1272:【例9.16】分组背包
    一本通 1292:宠物小精灵之收服
    一本通 1271:【例9.15】潜水员
  • 原文地址:https://www.cnblogs.com/storz/p/10191369.html
Copyright © 2011-2022 走看看