• 【51nod】1531 树上的博弈


    题解

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

    我们求最大值
    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('
    ')
    #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();
    }
    
  • 相关阅读:
    Asp.Net Web API 2第八课——Web API 2中的属性路由
    Asp.Net Web API 2第七课——Web API异常处理
    Asp.Net Web API 2第六课——Web API路由和动作选择
    Asp.Net Web API 2第五课——Web API路由
    开始学习python
    BMI 小程序 购物车
    深浅copy 文件操作
    字典 dict 集合set
    基本数据类型 (str,int,bool,tuple,)
    python 运算符
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9189146.html
Copyright © 2020-2023  润新知