zoukankan      html  css  js  c++  java
  • BZOJ3037创世纪

    解析

    首先如果考虑是树的情况那建完反图就跑一个dp就完事了。设 (dp[x][0/1]) 代表节点 (x) 选还是不选。有转移方程:(dp[x][0]=sum_{yin son(x)} max(dp[y][0],dp[y][1]))(dp[x][1]=dp[x][0]-(min_{yin son(x)} max(dp[y][0],dp[y][1]))+1)

    但这是一道基环树,其实差不多。首先基环树的套路就是先找到还然后再在环上处理。考虑是强行断环还是复制一遍。

    这道题应该是强行断环,假设断的是 ((s,t)) 这一条边(这里是原图),那么分两种情况讨论。

    1. s一定不选。这种情况碰到t的时候(dp[t][1])就直接等于(dp[t][0]+1)就好了。最后答案是(dp[s][0])

    2. s一定选。这种情况就直接正常跑就好了。最后答案是(dp[s][1])

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 1000005;
    template <typename T> void read(T &x) {
    	T f = 1;
    	char ch = getchar();
    	for (; '0' > ch || ch > '9'; ch = getchar()) if (ch == '-') f = -1;
    	for (x = 0; '0' <= ch && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
    	x *= f;
    }
    int n;
    int fa[MAXN];
    int u, v;
    vector<int> vec[MAXN];
    bool vis[MAXN];
    int dp[MAXN][2];
    int ans;
    void get_loop(int x) {
    	if (vis[x]) {
    		u = x;
    		v = fa[x];
    		return;
    	}
    	vis[x] = true;
    	get_loop(fa[x]);
    }
    void dfs(int x, bool zsy) {
    	dp[x][0] = dp[x][1] = 0;
    	vis[x] = 1;
    	for (int i = 0; i < (int)vec[x].size(); i++) {
    		int y = vec[x][i];
    		if (y != u) {
    			dfs(y, zsy);
    			dp[x][0] += max(dp[y][0], dp[y][1]); 
    		}
    	}
    	if (zsy) {
    		if (x == v) {
    			dp[x][1] = dp[x][0] + 1; 
    		} else {
    			for (int i = 0; i < (int)vec[x].size(); i++) {
    				int y = vec[x][i];
    				if (y != u) {
    					dp[x][1] = max(dp[x][1], dp[x][0] - max(dp[y][0], dp[y][1]) + dp[y][0] + 1);
    				}
    			}
    		}
    	} else {
    		for (int i = 0; i < (int)vec[x].size(); i++) {
    			int y = vec[x][i];
    			if (y != u) {
    				dp[x][1] = max(dp[x][1], dp[x][0] - max(dp[y][0], dp[y][1]) + dp[y][0] + 1);
    			}
    		}
    	}
    }
    int main() {
    	read(n);
    	for (int i = 1; i <= n; i++) {
    		read(fa[i]);
    		vec[fa[i]].push_back(i);
    	}
    	for (int i = 1; i <= n; i++) {
    		if (!vis[i]) {
    			int cur = 0;
    			get_loop(i);
    			dfs(u, 1);
    			cur = max(cur, dp[u][0]);
    			dfs(u, 0);
    			cur = max(cur, dp[u][1]);
    			ans += cur;
    		}
    	}
    	printf("%d", ans);
    	return 0;
    }
    

    编辑

  • 相关阅读:
    JS原生带小白点轮播图
    JS原生轮播图
    Vue.js小案例(2)
    Vue.js小案例(1)
    Vuejs入门级简单实例
    Vue.js简单入门
    微信登录oauth2.0
    PHP四维数组、三维数组封装遍历
    常用linux命令30个
    好架构是进化来的,不是设计来的
  • 原文地址:https://www.cnblogs.com/zcr-blog/p/14030653.html
Copyright © 2011-2022 走看看