zoukankan      html  css  js  c++  java
  • BZOJ 1040 骑士(环套树DP)

    如果m=n-1,显然这就是一个经典的树形dp。

    现在是m=n,这是一个环套树森林,破掉这个环后,就成了一个树,那么这条破开的边连接的两个顶点不能同时选择。我们可以对这两个点进行两次树形DP根不选的情况。

    那么答案就是每个森林的max()之和。

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-3
    # define MOD 1000000007
    # define INF (LL)1<<60
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=1000005;
    //Code begin...
    
    struct Edge{int p, next, flag;}edge[N<<1];
    int head[N], cnt=2, node[N], res[2], p;
    bool vis[N];
    LL dp[2][N][2];
    
    void add_edge(int u, int v){edge[cnt].p=v; edge[cnt].next=head[u]; head[u]=cnt++;}
    
    void dfs(int x, int fa)
    {
        vis[x]=true;
        for (int i=head[x]; i; i=edge[i].next) {
            int v=edge[i].p;
            if (v==fa) continue;
            if (vis[v]==true) {
                if (p==0) res[0]=x, res[1]=v, p=1, edge[i].flag=edge[i^1].flag=1;
                continue;
            }
            dfs(v,x);
        }
    }
    void dfs_dp(int x, int fa, int flag)
    {
        for (int i=head[x]; i; i=edge[i].next) {
            int v=edge[i].p;
            if (v==fa||edge[i].flag) continue;
            dfs_dp(v,x,flag);
            dp[flag][x][0]+=max(dp[flag][v][0],dp[flag][v][1]);
            dp[flag][x][1]+=dp[flag][v][0];
        }
        dp[flag][x][1]+=node[x];
    }
    int main ()
    {
        int n, u, w;
        LL ans=0;
        scanf("%d",&n);
        FOR(i,1,n) scanf("%d%d",&w,&u), add_edge(u,i), add_edge(i,u), node[i]=w;
        FOR(i,1,n) {
            if (vis[i]) continue;
            p=0; dfs(i,0);
            dfs_dp(res[0],0,0); dfs_dp(res[1],0,1);
            ans+=max(dp[0][res[0]][0],dp[1][res[1]][0]);
        }
        printf("%lld
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    RabbitMQ消息队列———安装(一)
    Tornado之自定义异步非阻塞的服务器和客户端
    爬虫之解析微信的网页版(分析后台,不分析前端)
    阻塞I/O、非阻塞I/O和I/O多路复用
    Git之安装管理
    MongoDB下载以及安装
    Python3学习笔记(十六):随机数模块random
    Python3学习笔记(十五):常用时间模块time和datetime
    Python3学习笔记(十四):可迭代对象、迭代器和生成器
    unittest详解(七) 自动生成测试报告
  • 原文地址:https://www.cnblogs.com/lishiyao/p/6489894.html
Copyright © 2011-2022 走看看