T1 [HAOI2010]软件安装

https://daniu.luogu.org/problem/show?pid=2515

树上背包,如果有i必须有j,j作为i的父节点

O(nm²)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 101
#define M 501
using namespace std;
int y[N],h[N],x[N];
int dfn[N],low[N],st[N],top,tot;
bool vis[N];
int cnt,ny[N],nh[N],col[N];
int dp[N][M],m;
int to[M],nxt[M],front[N];
int to2[M],nxt2[M],front2[M];
void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
}
void add(int u,int v)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
}
void add2(int u,int v)
{
to2[++tot]=v; nxt2[tot]=front2[u]; front2[u]=tot;
}
void tarjan(int u)
{
dfn[u]=low[u]=++tot;
vis[u]=true;
st[++top]=u;
if(x[u])
{
if(!dfn[x[u]]) tarjan(x[u]),low[u]=min(low[u],low[x[u]]);
else if(vis[x[u]]) low[u]=min(low[u],dfn[x[u]]);
}
if(dfn[u]==low[u])
{
cnt++;
while(st[top]!=u)
{
ny[cnt]+=y[st[top]];
nh[cnt]+=h[st[top]];
vis[st[top]]=false;
col[st[top]]=cnt;
top--;
}
ny[cnt]+=y[u];
nh[cnt]+=h[u];
vis[u]=false;
col[u]=cnt;
top--;
}
}
void dfs(int now)
{
for(int i=ny[now];i<=m;i++) dp[now][i]=nh[now];
for(int i=front2[now];i;i=nxt2[i])
{
dfs(to2[i]);
for(int j=m;j>=ny[now];j--)
for(int k=;k<=j-ny[now];k++)
dp[now][j]=max(dp[now][j],dp[now][j-k]+dp[to2[i]][k]);
}
}
int main()
{
int n;
read(n); read(m);
for(int i=;i<=n;i++) read(y[i]);
for(int i=;i<=n;i++) read(h[i]);
for(int i=;i<=n;i++)
{
read(x[i]);
add(x[i],i);
}
tot=;
for(int i=;i<=n;i++)
if(!dfn[i]) tarjan(i);
memset(vis,false,sizeof(vis));
tot=;
for(int i=;i<=n;i++)
if(col[i]!=col[x[i]])
add2(col[x[i]],col[i]),vis[col[i]]=true;
for(int i=;i<=cnt;i++)
if(!vis[i]) add2(,i);
dfs();
printf("%d",dp[][m]);
}

可以优化值O(nm),即每次都将要处理的子树和根节点看做一个整体

在dfs子树前,将根节点的值赋值给子节点

具体参考XCH的《浅谈几类背包问题》

https://wenku.baidu.com/view/d59b42fe04a1b0717fd5dd72.html

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=,maxm=;
struct edge
{
int u,v;
};
struct edge Edge[maxn];
int bel[maxn],n,m,col,hi[maxn],yi[maxn],head[maxn],tag,dp[maxn][maxm];
int E[maxn<<],V[maxn<<],cnt,ci[maxn],vi[maxn],dfn[maxn],low[maxn];
int sta[maxn],top,num;
bool vis[maxn];
inline void in(int &now)
{
char Cget;now=;while((Cget=getchar())>''||Cget<'');
while(Cget>=''&&Cget<='')now=now*+Cget-'',Cget=getchar();
}
void tarjan(int now)
{
dfn[now]=low[now]=++tag,sta[++top]=now;
for(int i=head[now];i;i=E[i])
if(!bel[V[i]])
if(dfn[V[i]]) low[now]=min(low[now],dfn[V[i]]);
else tarjan(V[i]),low[now]=min(low[now],low[V[i]]);
if(low[now]==dfn[now])
{
col++;
while(sta[top]!=now)
{
bel[sta[top]]=col;
vi[col]+=yi[sta[top]];
ci[col]+=hi[sta[top]];
top--;
}
bel[now]=col,vi[col]+=yi[now],ci[col]+=hi[now],top--;
}
}
void dfs(int now,int lit)
{
if(lit<=) return;
int v;
for(int i=head[now];i;i=E[i])
if(lit>=vi[V[i]])
{
v=V[i];
for(int e=;e<=lit;e++)
dp[v][e]=dp[now][e];
dfs(v,lit-vi[v]);
for(int e=lit;e>=vi[v];e--)
dp[now][e]=max(dp[now][e],dp[v][e-vi[v]]+ci[v]);
}
}
int main()
{
in(n),in(m);
for(int i=;i<=n;i++) in(yi[i]);
for(int i=;i<=n;i++) in(hi[i]);
int u,v;
for(int i=;i<=n;i++)
{
in(u),v=i;
if(u!=)
{
E[++cnt]=head[u],V[cnt]=v,head[u]=cnt;
}
Edge[i].u=u,Edge[i].v=v;
}
for(int i=;i<=n;i++)
if(!dfn[i])
tarjan(i);
num=n,cnt=;
memset(head,,sizeof(head));
for(int i=;i<=num;i++)
if(bel[Edge[i].u]!=bel[Edge[i].v])
{
if(Edge[i].u!=)
{
E[++cnt]=head[bel[Edge[i].u]];
V[cnt]=bel[Edge[i].v];
head[bel[Edge[i].u]]=cnt;
vis[bel[Edge[i].v]]=true;
}
else
{
E[++cnt]=head[n+];
V[cnt]=bel[Edge[i].v];
vis[bel[Edge[i].v]]=true;
head[n+]=cnt;
}
}
for(int i=;i<=col;i++)
if(!vis[i])
{
E[++cnt]=head[n+];
V[cnt]=i;
head[n+]=cnt;
}
dfs(n+,m);
cout<<dp[n+][m];
fclose(stdin),fclose(stdout);
return ;
}

T2 codevs 3305 水果姐逛水果街Ⅱ

http://codevs.cn/problem/3305/

树链剖分维护前面减后面的最大值,后面减前面的最大值

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#define lson k<<1
#define rson k<<1|1
using namespace std;
const int N=;
int front[N],to[N<<],nxt[N<<],tot,dfn[N],id[N],a[N];
int ls[N<<],rs[N<<],mi[N<<],mx[N<<];
int n,siz[N],dep[N],bl[N],fa[N];
struct node
{
int x,y,z;
};
inline void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-'' ; c=getchar(); }
}
void add(int u,int v)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
}
void dfs1(int x,int f)
{
siz[x]=;
for(int i=front[x];i;i=nxt[i])
if(to[i]!=f)
{
dep[to[i]]=dep[x]+;
fa[to[i]]=x;
dfs1(to[i],x);
siz[x]+=siz[to[i]];
}
}
void dfs2(int x,int top)
{
bl[x]=top;
dfn[x]=++tot;
id[tot]=x;
int y=;
for(int i=front[x];i;i=nxt[i])
if(to[i]!=fa[x] && siz[to[i]]>siz[y]) y=to[i];
if(!y) return;
dfs2(y,top);
for(int i=front[x];i;i=nxt[i])
if(to[i]!=fa[x] && to[i]!=y) dfs2(to[i],to[i]);
}
inline void up(int k)
{
mi[k]=min(mi[lson],mi[rson]);
mx[k]=max(mx[lson],mx[rson]);
ls[k]=max(mx[rson]-mi[lson],max(ls[lson],ls[rson]));
rs[k]=max(mx[lson]-mi[rson],max(rs[lson],rs[rson]));
}
void build(int k,int l,int r)
{
if(l==r)
{
mi[k]=mx[k]=a[id[l]];
return;
}
int mid=l+r>>;
build(lson,l,mid);
build(rson,mid+,r);
up(k);
}
int getlca(int u,int v)
{
while(bl[u]!=bl[v])
{
if(dep[bl[u]]<dep[bl[v]]) swap(u,v);
u=fa[bl[u]];
}
return dep[u]>dep[v] ? v : u;
}
node qleft(int k,int l,int r,int opl,int opr)
{
if(l>=opl && r<=opr) return (node){mi[k],mx[k],ls[k]};
int mid=l+r>>;
if(opr<=mid) return qleft(lson,l,mid,opl,opr);
if(opl>mid) return qleft(rson,mid+,r,opl,opr);
node lch=qleft(lson,l,mid,opl,opr),rch=qleft(rson,mid+,r,opl,opr);
return (node){min(lch.x,rch.x),max(lch.y,rch.y),max(rch.y-lch.x,max(lch.z,rch.z))};
}
node fleft(int x,int y)
{
if(bl[x]==bl[y]) return qleft(,,n,dfn[y],dfn[x]);
node lch,rch=qleft(,,n,dfn[bl[x]],dfn[x]);
x=fa[bl[x]];
//if(id[bl[x]]<id[bl[y]]) swap(x,y);
while(bl[x]!=bl[y])
{
lch=qleft(,,n,dfn[bl[x]],dfn[x]);
rch.z=max(rch.y-lch.x,max(lch.z,rch.z));
rch.x=min(lch.x,rch.x),rch.y=max(lch.y,rch.y);
x=fa[bl[x]];
}
lch=qleft(,,n,dfn[y],dfn[x]);
rch.z=max(rch.y-lch.x,max(lch.z,rch.z));
rch.x=min(lch.x,rch.x),rch.y=max(lch.y,rch.y);
return rch;
}
node qright(int k,int l,int r,int opl,int opr)
{
if(l>=opl && r<=opr) return (node){mi[k],mx[k],rs[k]};
int mid=l+r>>;
if(opr<=mid) return qright(lson,l,mid,opl,opr);
if(opl>mid) return qright(rson,mid+,r,opl,opr);
node lch=qright(lson,l,mid,opl,opr),rch=qright(rson,mid+,r,opl,opr);
return (node){ min(lch.x,rch.x),max(lch.y,rch.y),max(lch.y-rch.x,max(lch.z,rch.z))};
}
node fright(int x,int y)
{
if(bl[x]==bl[y]) return qright(,,n,dfn[y],dfn[x]);
node rch=qright(,,n,dfn[bl[x]],dfn[x]),lch;
x=fa[bl[x]];
// if(id[bl[x]]<id[bl[y]]) swap(x,y);
while(bl[x]!=bl[y])
{
lch=qright(,,n,dfn[bl[x]],dfn[x]);
rch.z=max(lch.y-rch.x,max(lch.z,rch.z));
rch.x=min(lch.x,rch.x),rch.y=max(lch.y,rch.y);
x=fa[bl[x]];
}
lch=qright(,,n,dfn[y],dfn[x]);
rch.z=max(lch.y-rch.x,max(lch.z,rch.z));
rch.x=min(lch.x,rch.x),rch.y=max(lch.y,rch.y);
return rch;
}
int main()
{
memset(mi,/,sizeof(mi));
int m,u,v,lca;
read(n);
for(int i=;i<=n;i++) read(a[i]);
for(int i=;i<n;i++) read(u),read(v),add(u,v);
dfs1(,);
tot=;
dfs2(,);
build(,,n);
read(m);
while(m--)
{
read(u),read(v);
lca=getlca(u,v);
if(u==lca) printf("%d\n",fleft(v,lca).z);
else if(v==lca) printf("%d\n",fright(u,lca).z);
else
{
node lch=fleft(v,lca),rch=fright(u,lca);
printf("%d\n",max(lch.y-rch.x,max(lch.z,rch.z)));
}
}
return ;
}

T3 hdu 1798 50 years, 50 colors

http://acm.hdu.edu.cn/showproblem.php?pid=1498

枚举颜色

如果(x,y)有气球,则由x向y连边

然后二分图最小点覆盖=最大匹配数

#include<cstdio>
#include<cstring>
using namespace std;
int a[][];
bool v[],vv[];
int match[];
int tot,front[],to[],nxt[];
int ans[];
void add(int u,int v)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
}
bool dfs(int u)
{
for(int i=front[u];i;i=nxt[i])
if(!v[to[i]])
{
v[to[i]]=true;
if(!match[to[i]] || dfs(match[to[i]]))
{
match[to[i]]=u;
return true;
}
}
return false;
}
int main()
{
//freopen("T3.in","r",stdin);
//freopen("T3.out","w",stdout);
int n,k,res;
bool ok;
while(scanf("%d%d",&n,&k))
{
if(!n) return ;
memset(vv,false,sizeof(vv));
ok=false;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
scanf("%d",&a[i][j]),vv[a[i][j]]=true;
ans[]=;
for(int i=;i<=;i++)
if(vv[i])
{
tot=;
memset(front,,sizeof(*front)*(n+));
res=;
for(int j=;j<=n;j++)
for(int k=;k<=n;k++)
if(a[j][k]==i) add(j,k);
memset(match,,sizeof(*match)*(n+));
for(int j=;j<=n;j++)
{
memset(v,false,sizeof(*v)*(n+));
if(dfs(j)) res++;
}
if(res>k) ans[++ans[]]=i;
}
if(!ans[]) printf("-1");
else
{
for(int i=;i<ans[];i++) printf("%d ",ans[i]);
printf("%d",ans[ans[]]);
}
printf("\n");
}
}

NOIP模拟赛10的更多相关文章

  1. 【noip模拟赛10】奇怪的贸易 高精度

    描述 刚结束了CS战斗的小D又进入了EVE的游戏世界,在游戏中小D是一名商人,每天要做的事情就是在这里买东西,再运到那里去卖.这次小D来到了陌生的X星,X星上有n种货物,小D决定每种都买走一些,他用a ...

  2. NOIP模拟赛10 题解

    t3: 题意 给你一棵树,然后每次两种操作:1.给一个节点染色 : 2. 查询一个节点与任意已染色节点 lca 的权值的最大值 分析 考虑一个节点被染色后的影响:令它的所有祖先节点(包括自身)的所有除 ...

  3. 10.17 NOIP模拟赛

    目录 2018.10.17 NOIP模拟赛 A 咒语curse B 神光light(二分 DP) C 迷宫maze(次短路) 考试代码 B 2018.10.17 NOIP模拟赛 时间:1h15min( ...

  4. 10.16 NOIP模拟赛

    目录 2018.10.16 NOIP模拟赛 A 购物shop B 期望exp(DP 期望 按位计算) C 魔法迷宫maze(状压 暴力) 考试代码 C 2018.10.16 NOIP模拟赛 时间:2h ...

  5. NOIP模拟赛20161022

    NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...

  6. contesthunter暑假NOIP模拟赛第一场题解

    contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...

  7. NOIP模拟赛 by hzwer

    2015年10月04日NOIP模拟赛 by hzwer    (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...

  8. 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程

    数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...

  9. 队爷的讲学计划 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...

随机推荐

  1. Scrum立会报告+燃尽图(十月十日总第一次):选题

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2190 Scrum立会master:付佳 一.小组介绍 组长:付佳 组员: ...

  2. 欢迎来怼--第二十三次Scrum会议

    一.小组信息 队名:欢迎来怼 小组成员 队长:田继平 成员:李圆圆,葛美义,王伟东,姜珊,邵朔,阚博文 小组照片 二.开会信息 时间:2017/11/11 17:20~17:55,总计35min. 地 ...

  3. KNN算法之图像处理二

    1.看了诸多博客,初步得到结论是:KNN不适合做图像分类. 2.如果偏要用此方法进行图像分类,距离计算为:对应的每个像素代表的像素值进行绝对差值计算,最后求和.这就是“图像的距离”

  4. 博弈---ZOJ 3057 Beans Game(DP博弈)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3057 有豆类三个桩.TT和DD挑选任意数量的豆子从任何两堆轮流任何桩或相同 ...

  5. webService —— soap

    package soupTest; import javax.jws.WebMethod; import javax.jws.WebService; import javax.xml.ws.Endpo ...

  6. SpringCloud——服务网关

    1.背景 上篇博客<SpringCloud--Eureka服务注册和发现>中介绍了注册中心Eureka.服务提供者和服务消费者.这篇博客我们将介绍服务网关. 图(1) 未使用服务网关的做法 ...

  7. linux下c/c++的文件操作

    opendir,readdir,closedir, stat()查询文件状态 open(), O_TRUNC这个Flag会把打开的文件清零... 文件锁:fcntl, F_GETLK , F_SETL ...

  8. php反射机制应用

    用来获取指定的类的信息,包括类中的属性,方法,方法权限,注释等 用途:1.thinkPHP框架中的前置,后置控制器的实现 2.与debug_backtrace函数结合使用,文件调用的权限管理 使用方法 ...

  9. python 小数保留位数

    利用round(number[, ndigit] )函数四舍五入 保留浮点数的小数点. 如保留小数点后两位. num = 9.2174 new_num = round( num , 2 ) 则new_ ...

  10. 第91天:CSS3 属性选择器、伪类选择器和伪元素选择器

    一.属性选择器 其特点是通过属性来选择元素,具体有以下5种形式: 1.E[attr] 表示存在attr属性即可:    div[class] 2.E[attr=val] 表示属性值完全等于val:   ...