码迷,mamicode.com
首页 > 其他好文 > 详细

【51nod】1531 树上的博弈

时间:2018-06-15 23:33:27      阅读:296      评论:0      收藏:0      [点我收藏+]

标签:转移   struct   stream   大于等于   大于   ios   freopen   next   long   

题解

我们发现每次决策的时候,我们可以判断某个点的决策,至少小于等于几个点或者至少大于等于几个点

我们求最大值
dp[u][1 / 0]
dp[u][1]表示u这个点先手,至少大于等于几个点
dp[u][0]表示u这个点后手走,至少大于等于几个点
转移的时候从dp[u][1]取所有点dp[v][0]最小的那个
dp[u][0]就是所有dp[v][1]的和

最小值
dp[u][1]表示u这个点先手,至少小于等于几个点
dp[u][0]表示u这个点后手,至少小于等于几个点
转移的时候dp[u][0]取所有dp[v][1]最小的那个
dp[u][1]是所有dp[v][1]的和

统计的叶子的时候有个trick就是,一条链的话,根节点点度为1,不算叶子
同时特判只有一个点的情况

代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#define enter putchar(‘\n‘)
#define space putchar(‘ ‘)
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < ‘0‘ || c > ‘9‘) {
        if(c == ‘-‘) f = -1;
        c = getchar();
    }
    while(c >= ‘0‘ && c <= ‘9‘) {
        res = res * 10 + c - ‘0‘;
        c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {putchar(‘-‘);x = -x;}
    if(x >= 10) {
        out(x / 10);
    }
    putchar(‘0‘ + x % 10);
}
int N,M;
struct node {
    int to,next;
}E[MAXN * 2];
int head[MAXN],sumE,D[MAXN],dp[MAXN][2];
void add(int u,int v) {
    E[++sumE].to = v;
    E[sumE].next = head[u];
    head[u] = sumE;
}
void Init() {
    read(N);
    int u,v;
    for(int i = 1 ; i < N ; ++i) {
        read(u);read(v);add(u,v);add(v,u);
        D[u]++;D[v]++;
    }
    for(int i = 2 ; i <= N ; ++i) {
        if(D[i] == 1) ++M;
    }
}
void dfs1(int u,int fa) {
    int son = 0;
    dp[u][1] = M;dp[u][0] = 0;
    for(int i = head[u] ; i ; i = E[i].next) {
        int v = E[i].to;
        if(v != fa) {
            dfs1(v,u);++son;
            dp[u][1] = min(dp[v][0],dp[u][1]);
            dp[u][0] += dp[v][1];
        }
    }
    if(son == 0) dp[u][1] = dp[u][0] = 1;
}
void dfs2(int u,int fa) {
    int son = 0;
    dp[u][0] = M;dp[u][1] = 0;
    for(int i = head[u] ; i ; i = E[i].next) {
        int v = E[i].to;
        if(v != fa) {
            dfs2(v,u);++son;
            dp[u][1] += dp[v][0];
            dp[u][0] = min(dp[v][1],dp[u][0]);
        }
    }
    if(son == 0) dp[u][1] = dp[u][0] = 1;
}
void Solve() {
    if(M <= 1) {
        out(1);space;out(1);enter;
        return;
    }
    memset(dp,0,sizeof(dp));
    dfs1(1,0);
    out(M - dp[1][1] + 1);space;
    memset(dp,0,sizeof(dp));
    dfs2(1,0);
    out(dp[1][1]);enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Init();
    Solve();
}

【51nod】1531 树上的博弈

标签:转移   struct   stream   大于等于   大于   ios   freopen   next   long   

原文地址:https://www.cnblogs.com/ivorysi/p/9189146.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!