zoukankan      html  css  js  c++  java
  • 题解 P1273 【有线电视网】

    题目链接:Link

    Problem

    Solution

    这题显然是个树形dp之树上分组背包,信心满满地写出转移方程后,发现:时间复杂度 $ O(n^3) $ ???
    但仔细观察了讨论区和题解后,发现,这是 $ O(n^2) $ 的???
    于是我开始尝试牙刷图、分块牙刷图、菊花图、扫帚图。。。。卡标算。。。燃鹅失败了。。。
    证明:
    暂且先认为所有节点都会产生贡献,这不会影响最坏复杂。
    考虑一下最里面循环的过程,可以认为等效于枚举之前的子树里的节点与当前子树的节点的两两组合。
    KHbCyF.png
    不难发现此时u节点是这样的点对的lca,因此:每一对点只会在它们的lca上产生一次计算量
    由此可证,时间复杂度为 $ O(n^2) $ 。

    Code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=3005;
    struct Edge { int v,w; Edge *nxt; };
    int n,m,a[maxn],f[maxn][maxn],t[maxn];
    Edge mem[maxn],*G[maxn],*ecnt=mem;
    inline void AddEdge(int u,int v,int w) { ecnt->v=v; ecnt->w=w; ecnt->nxt=G[u]; G[u]=ecnt++; }
    int dfs(int u)
    {
    	if(u>n-m)
    	{
    		f[u][1]=a[u];
    		return 1;
    	}
    	int tot=0,v,sz;
    	for(Edge *it=G[u];it;it=it->nxt)
    	{
    		v=it->v; sz=dfs(v);
    		for(int i=0;i<=tot;i++) t[i]=f[u][i];
    		for(int i=0;i<=tot;i++)
    			for(int j=0;j<=sz;j++)
    				f[u][i+j]=max(f[u][i+j],t[i]+f[v][j]-it->w);
    		tot+=sz;
    	}
    	return tot;
    }
    int main()
    {
    	#ifdef local
    	freopen("pro.in","r",stdin);
    	#endif
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n-m;i++)
    	{
    		int tot,v,w;
    		scanf("%d",&tot);
    		while(tot-->0) { scanf("%d%d",&v,&w); AddEdge(i,v,w); }
    	}
    	for(int i=n-m+1;i<=n;i++) scanf("%d",&a[i]);
    	memset(f,~0x3f,sizeof(f));
    	for(int i=1;i<=n;i++) f[i][0]=0;
    	dfs(1);
    	for(int i=m;i>=0;i--) if(f[1][i]>=0) { printf("%d
    ",i); return 0; }
    	return 0;
    }
    
  • 相关阅读:
    centos7 安装docker 对应的 rabbitmq3.6.15
    golang中defer的使用规则
    Yii2-redis 不用 composer 的安装
    安装并使用PHPunit
    PHP Taint – 一个用来检测XSS/SQL/Shell注入漏洞的扩展
    SQL Antipatterns——SQL 反模式(二)
    tp5 No input file specified.
    vue 封装自定义组件
    判断微信访问
    phalcon windows下安装phalcon-devtools 官网的坑
  • 原文地址:https://www.cnblogs.com/happyZYM/p/11768056.html
Copyright © 2011-2022 走看看