zoukankan      html  css  js  c++  java
  • [ZJOI2008]骑士

    看题时像一个独立集的题,看了数据之后。。。。

    主要在于:每个骑士都有且仅有一个自己最厌恶的骑士。

    所以整个图是多个联通块,每联通块都是一个环和一些树。

    先在树上做dp,

    可以枚举环上两点,分别不取。

    也可以写个环dp。

    (我写的是环dp)

    /**
     * Problem:[ZJOI2008]p5
     * Author:Shun Yao
     * Time:2013.5.30
     * Result:Accepted
     * Memo:DP
     */
    
    #include <cstring>
    #include <cstdio>
    
    const long Maxn = 1000005;
    
    long long max(long long x, long long y) {
    	return x > y ? x : y;
    }
    
    void swap(long &x, long &y) {
    	x ^= y;
    	y ^= x;
    	x ^= y;
    }
    
    long n, A[Maxn], fa[Maxn], ff[Maxn];
    long long ans, f[Maxn][2];
    
    class gnode {
    public:
    	long v;
    	gnode *next;
    	gnode() {}
    	~gnode() {}
    	gnode(long V, gnode *ne):v(V), next(ne) {}
    } *g[Maxn];
    
    void add(long x, long y) {
    	g[x] = new gnode(y, g[x]);
    	g[y] = new gnode(x, g[y]);
    }
    
    void DP_Tree(long x) {
    	static long q[Maxn], *l, *r;
    	static gnode *e;
    	r = (l = &(*q = x)) + 1;
    	while (l != r) {
    		for (e = g[*l]; e; e = e->next)	if (!ff[e->v]) {
    			ff[e->v] = *l;
    			*(r++) = e->v;
    		}
    		++l;
    	}
    	do {
    		--l;
    		f[*l][0] = 0;
    		f[*l][1] = A[*l];
    		for (e = g[*l]; e; e = e->next) if (ff[e->v] == *l) {
    			f[*l][0] += f[e->v][1];
    			f[*l][1] += f[e->v][0];
    		}
    		f[*l][1] = max(f[*l][1], f[*l][0]);
    	} while (l != q);
    }
    
    long q[Maxn], *l, *r;
    long st[Maxn << 1], stl;
    long ST[Maxn], STl;
    long d[Maxn];
    long long h[Maxn];
    void DP(long x) {
    	static gnode *e;
    	static long a, b;
    	r = (l = &(*q = x)) + 1;
    	fa[x] = -1;
    	stl = 0;
    	STl = 0;
    	while (l != r) {
    		for (e = g[*l]; e; e = e->next) if (e->v != fa[*l]) {
    			if (!fa[e->v]) {
    				d[e->v] = d[*l] + 1;
    				fa[e->v] = *l;
    				*(r++) = e->v;
    			} else if (!stl) {
    				a = *l;
    				b = e->v;
    				if (d[a] < d[b])
    					swap(a, b);
    				while (d[a] > d[b]) {
    					st[++stl] = a;
    					a = fa[a];
    				}
    				while (a != b) {
    					st[++stl] = a;
    					ST[++STl] = b;
    					a = fa[a];
    					b = fa[b];
    				}
    				st[++stl] = a;
    				while (STl)
    					st[++stl] = ST[STl--];
    			}
    		}
    		++l;
    	}
    	static long i;
    	for (i = 1; i <= stl; ++i)
    		ff[st[i]] = -1;
    	for (i = 1; i <= stl; ++i)
    		DP_Tree(st[i]);
    	static long long ret;
    	h[0] = 0;
    	h[1] = f[st[1]][1];
    	for (i = 2; i < stl; ++i)
    		h[i] = max(h[i - 2] + f[st[i - 1]][0] + f[st[i]][1], h[i - 1] + f[st[i]][0]);
    	ret = h[stl - 1] + f[st[stl]][0];
    	h[1] = 0;
    	h[2] = f[st[2]][1];
    	for (i = 3; i <= stl; ++i)
    		h[i] = max(h[i - 2] + f[st[i - 1]][0] + f[st[i]][1], h[i - 1] + f[st[i]][0]);
    	ans += max(h[stl] + f[st[1]][0], ret);
    }
    
    int main() {
    	static long i, B;
    	freopen("p5.in", "r", stdin);
    	freopen("p5.out", "w", stdout);
    	scanf("%ld", &n);
    	for (i = 1; i <= n; ++i)
    		g[i] = 0;
    	for (i = 1; i <= n; ++i) {
    		scanf("%ld%ld", A + i, &B);
    		add(i, B);
    	}
    	memset(d, 0, sizeof d);
    	memset(fa, 0, sizeof fa);
    	memset(ff, 0, sizeof ff);
    	ans = 0;
    	for (i = 1; i <= n; ++i)
    		if (!fa[i])
    			DP(i);
    	printf("%lld", ans);
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    iOS开发常用的第三方框架
    回传值(代理、通知、block)
    给控制器添加工具栏(Swift语言)
    Swift语言 代码添加文本输入框 和 占位文本
    MD5加密运算
    Xcode7.0设置网络白名单
    base64加密解密文件
    关于iOS应用管理之九宫格的坐标计算以及与UIScrollView的结合
    3、Struts2中的参数传值
    2、Action的多种写法配置
  • 原文地址:https://www.cnblogs.com/hsuppr/p/3115462.html
Copyright © 2011-2022 走看看