zoukankan      html  css  js  c++  java
  • 洛谷1273 有线电视网

    原题链接

    显然是一个树形(DP),状态转移则是裸的分组背包模型。
    先将边权转换为点权,即每个转播台或用户的权值为原来的点权减去它到父亲的边权(没有的作为(0)去计算),记为(V[x])
    (f[x][k])表示以(x)为根的子树中,选择(k)个用户所能达到的最大收入,(size[x])表示以(x)为根的子树中用户的个数。
    则对于(x)的一个儿子(y),有状态转移方程:

    (qquadqquad j = size[x] o 0, f[x][j] = maxlimits ^ {k = j o 0}{ f[x][j], f[x][j - k] + f[y][k] })

    在转移完毕时,再将(x)自身的权值加上:(i = size[x] o 1, f[x][i] = f[x][i] + V[x])
    初始化则是先将(f)全部赋为极小值,然后在(DFS)中赋初值:

    1. 不论(x)是什么,(f[x][0] = 0)
    2. (x)为用户,则(f[x][1] = V[x])

    最后的答案就是满足(f[x][k] geqslant 0)中最大的(k)
    虽然这个方法理论上是(O(n^3))的,但因为大多数都是冗余的状态,且实际实现的常数一般很小,所以是能够通过的。

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N = 3010;
    const int M = N << 1;
    int fi[N], di[M], ne[M], f[N][N], V[N], si[N], l, p;
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline void add(int x, int y)
    {
    	di[++l] = y;
    	ne[l] = fi[x];
    	fi[x] = l;
    }
    inline int maxn(int x, int y)
    {
    	return x > y ? x : y;
    }
    void dfs(int x, int fa)
    {
    	int i, j, k, y;
    	f[x][0] = 0;
    	if (x > p)
    	{
    		si[x] = 1;
    		f[x][1] = V[x];
    		return;
    	}
    	for (i = fi[x]; i; i = ne[i])
    		if ((y = di[i]) ^ fa)
    		{
    			dfs(y, x);
    			si[x] += si[y];
    			for (j = si[x]; ~j; j--)
    				for (k = j; ~k; k--)
    					f[x][j] = maxn(f[x][j], f[x][j - k] + f[y][k]);
    		}
    	for (i = si[x]; i; i--)
    		f[x][i] += V[x];
    }
    int main()
    {
    	int i, j, k, n, m, x, y;
    	n = re();
    	m = re();
    	p = y = n - m;
    	for (i = 1; i <= y; i++)
    		for (k = re(), j = 1; j <= k; j++)
    		{
    			x = re();
    			add(i, x);
    			add(x, i);
    			V[x] = -re();
    		}
    	for (i = 1; i <= m; i++)
    		V[y + i] += re();
    	memset(f, 250, sizeof(f));
    	dfs(1, 0);
    	for (i = n; i; i--)
    		if (f[1][i] >= 0)
    			break;
    	printf("%d", i);
    	return 0;
    }
    
  • 相关阅读:
    GitLab 远程 定时备份
    GitLab 本地 定时备份
    MATLAB格式化输出控制
    hilbert矩阵
    MATLAB符号运算
    双线性插值 分类: 图像处理 2015-07-28 15:14 7人阅读 评论(0) 收藏
    shamir叠像术 分类: 图像处理 2015-07-08 16:50 17人阅读 评论(1) 收藏
    cookies、sessionStorage和localStorage解释及区别
    微信小程序,组件之间带参数跳转+轮播图+冒泡事件+表单提交
    微信小程序,头部和底部设置需要注意的事项
  • 原文地址:https://www.cnblogs.com/Iowa-Battleship/p/9838257.html
Copyright © 2011-2022 走看看