test20181029 宝藏
题意

分析
考场做法
一眼看出是支持换根的树形dp。
用\(f(x,0/1)\)表示x及其子树中,从x出发,不一定/一定回到x的最大收益。
然后子树很好做。
换根的时候,我先计算后还原,需要考虑很多,调了很久。
后来知道可以用up,down状态转移,会好写一些,但要考虑得跟我先前打的差不多。
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#include<cassert>
#define rg register
#define il inline
#define co const
#pragma GCC optimize ("O0")
using namespace std;
template<class T> il T read()
{
T data=0;
int w=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(isdigit(ch))
data=10*data+ch-'0',ch=getchar();
return data*w;
}
template<class T> il T read(T&x)
{
return x=read<T>();
}
typedef long long ll;
const int INF=0x7fffffff;
co int MAXN=3e5+7;
struct Edge
{
int nx,to,w;
}E[MAXN<<1];
int head[MAXN],ecnt;
il void addedge(rg int x,rg int y,rg int w)
{
E[++ecnt].to=y,E[ecnt].w=w;
E[ecnt].nx=head[x],head[x]=ecnt;
}
int fa[MAXN],fw[MAXN];
int val[MAXN];
ll f[MAXN][2];
int maxv[MAXN],secv[MAXN];
il ll take(rg int y)
{
return max(0LL,f[y][0]-fw[y]);
}
il ll fetch(rg int y)
{
return max(0LL,f[y][1]-2*fw[y]);
}
il ll calc(rg int y)
{
return take(y)-fetch(y);
}
il void dfs1(rg int x,rg int fath)
{
fa[x]=fath;
f[x][1]=val[x];
for(rg int i=head[x];i;i=E[i].nx)
{
rg int y=E[i].to,w=E[i].w;
if(y==fath)
{
fw[x]=w;
continue;
}
dfs1(y,x);
f[x][1]+=fetch(y);
}
f[x][0]=f[x][1];
for(rg int i=head[x];i;i=E[i].nx)
{
rg int y=E[i].to;
if(y==fath)
continue;
if(calc(y)>calc(secv[x]))
{
secv[x]=y;
if(calc(secv[x])>calc(maxv[x]))
swap(secv[x],maxv[x]);
}
}
f[x][0]+=calc(maxv[x]);
}
ll fet[MAXN],calsec[MAXN],cal[MAXN];
il void dfs2(rg int x)
{
if(fa[x])
{ // f[fa] shouldn't change
fet[x]=fetch(x);
cal[x]=calc(x);
f[fa[x]][1]-=fet[x];
f[fa[x]][0]-=fet[x];
rg int w=fw[fa[x]];
fw[fa[x]]=fw[x];
f[x][1]+=fetch(fa[x]);
f[x][0]=f[x][1];
if(maxv[fa[x]]==x)
{
f[fa[x]][0]-=cal[x];
f[fa[x]][0]+=calsec[fa[x]];
}
if(calc(fa[x])>calc(secv[x]))
{
secv[x]=fa[x];
if(calc(secv[x])>calc(maxv[x]))
swap(secv[x],maxv[x]);
}
calsec[x]=calc(secv[x]);
f[x][0]+=calc(maxv[x]);
f[fa[x]][1]+=fet[x]; // restore
f[fa[x]][0]+=fet[x];
fw[fa[x]]=w;
if(maxv[fa[x]]==x)
{
f[fa[x]][0]-=calsec[fa[x]];
f[fa[x]][0]+=cal[x];
}
}
else
{
fet[x]=fetch(x);
calsec[x]=calc(secv[x]);
cal[x]=calc(x);
}
for(rg int i=head[x];i;i=E[i].nx)
{
rg int y=E[i].to;
if(y==fa[x])
continue;
dfs2(y);
}
}
int main()
{
freopen("treasure.in","r",stdin);
freopen("treasure.out","w",stdout);
rg int n=read<int>();
for(rg int i=1;i<n;++i)
{
rg int x=read<int>(),y=read<int>(),w=read<int>();
addedge(x,y,w);
addedge(y,x,w);
}
for(rg int i=1;i<=n;++i)
{
read(val[i]);
}
dfs1(1,0);
dfs2(1);
/* for(int i=1;i<=n;++i)
{
printf("%d:\n",i);
printf(" f0=%lld\tf1=%lld\n",f[i][0],f[i][1]);
}*/
for(rg int i=1;i<=n;++i)
{
printf("%lld\n",f[i][0]);
}
// fclose(stdin);
// fclose(stdout);
return 0;
}
标解

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<bitset>
using namespace std;
typedef long long ll;
const int N=610000;
int fi[N],ne[N],len[N],to[N];
ll dp0[N],dp1[N];
ll ans[N],wushi0[N],wushi1[N],val[N];
int pE,n;
//0:考虑回到原点;1:不回到原点
void addE(int u,int v,int l)
{
pE++;to[pE]=v;len[pE]=l;
ne[pE]=fi[u];fi[u]=pE;
}
void dfs(int u,int fa)
{
ll mx=0;
for (int j=fi[u];j;j=ne[j])
{
if (to[j]==fa) continue;
dfs(to[j],u);
if (dp0[to[j]]-2*len[j]>0)
{
dp0[u]+=dp0[to[j]]-2*len[j];
mx=max(mx,len[j]+dp1[to[j]]-dp0[to[j]]);
}
else mx=max(mx,dp1[to[j]]-len[j]);
}
dp0[u]+=val[u];
dp1[u]=dp0[u]+mx;
}
void dfs2(int u,int fa,int le)
{
ans[u]=max(dp0[u]+max(wushi1[u]-le,(ll)0),dp1[u]+max(wushi0[u]-le*2,(ll)0));
ll mx1=0,mx2=0;
for (int j=fi[u];j;j=ne[j])
{
if (to[j]==fa) continue;
ll now;
if (dp0[to[j]]-2*len[j]>0) now=len[j]+dp1[to[j]]-dp0[to[j]];
else now=dp1[to[j]]-len[j];
if (now>mx1) {mx2=mx1;mx1=now;}
else if (now>mx2) mx2=now;
}
ll now;
if (wushi0[u]-2*le>0) now=le+wushi1[u]-wushi0[u];
else now=wushi1[u]-le;
if (now>mx1) {mx2=mx1;mx1=now;}
else if (now>mx2) mx2=now;
for (int j=fi[u];j;j=ne[j])
{
if (to[j]==fa) continue;
wushi0[to[j]]=dp0[u]-max((ll)0,dp0[to[j]]-2*len[j])+max((ll)0,wushi0[u]-2*le);
ll now;
if (dp0[to[j]]-2*len[j]>0) now=len[j]+dp1[to[j]]-dp0[to[j]];
else now=dp1[to[j]]-len[j];
if (now==mx1) wushi1[to[j]]=wushi0[to[j]]+mx2;
else wushi1[to[j]]=wushi0[to[j]]+mx1;
}
for (int j=fi[u];j;j=ne[j])
if (to[j]!=fa) dfs2(to[j],u,len[j]);
}
int main()
{
freopen("treasure.in","r",stdin);
freopen("treasure.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<n;i++)
{
int u,v,l;scanf("%d%d%d",&u,&v,&l);
addE(u,v,l);addE(v,u,l);
}
for (int i=1;i<=n;i++) scanf("%d",&val[i]);
dfs(1,0);
for (int j=fi[1];j;j=ne[j])
if (dp0[to[j]]-2*len[j]>0)
wushi0[to[j]]=dp0[1]-(dp0[to[j]]-2*len[j]);
else wushi0[to[j]]=dp0[1];
ll mx1=0,mx2=0;
for (int j=fi[1];j;j=ne[j])
{
ll now;
if (dp0[to[j]]-2*len[j]>0) now=len[j]+dp1[to[j]]-dp0[to[j]];
else now=dp1[to[j]]-len[j];
if (now>mx1) {mx2=mx1;mx1=now;}
else if (now>mx2) mx2=now;
}
for (int j=fi[1];j;j=ne[j])
{
ll now;
if (dp0[to[j]]-2*len[j]>0) now=len[j]+dp1[to[j]]-dp0[to[j]];
else now=dp1[to[j]]-len[j];
if (now==mx1) wushi1[to[j]]=wushi0[to[j]]+mx2;
else wushi1[to[j]]=wushi0[to[j]]+mx1;
}
ans[1]=dp1[1];
for (int j=fi[1];j;j=ne[j]) dfs2(to[j],1,len[j]);
for (int i=1;i<=n;i++) printf("%lld\n",ans[i]);
return 0;
}
test20181029 宝藏的更多相关文章
- 算法:poj1066 宝藏猎人问题。
package practice; import java.util.Scanner; public class TreasureHunt { public static void main(Stri ...
- 【BZOJ-1924】所驼门王的宝藏 Tarjan缩点(+拓扑排序) + 拓扑图DP
1924: [Sdoi2010]所驼门王的宝藏 Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 787 Solved: 318[Submit][Stat ...
- zzulioj 1907小火山的宝藏交易(dfs记忆化搜索)
#include <stdio.h> #include <algorithm> #include <string.h> #include <vector> ...
- codevs3196 黄金宝藏
题目描述 Description 小毛终于到达宝藏点,他意外地发现有一个外星人(名叫Pluto).宝藏是一些太空黄金,有n堆排成一行,每堆中有xi颗黄金.小毛和Pluto决定轮流从中取出黄金,规则是每 ...
- bzoj 1924 [Sdoi2010]所驼门王的宝藏(构图,SCC,DP)
Description Input 第一行给出三个正整数 N, R, C. 以下 N 行,每行给出一扇传送门的信息,包含三个正整数xi, yi, Ti,表示该传送门设在位于第 xi行第yi列的藏宝宫室 ...
- (zzuli)1907 小火山的宝藏收益
Description 进去宝藏后, 小火山发现宝藏有N个房间,且这n个房间通过N-1道门联通. 每一个房间都有一个价值为Ai的宝藏, 但是每一个房间也都存在一个机关.如果小火山取走了这个房间的宝藏, ...
- zzuli 1907: 小火山的宝藏收益 邻接表+DFS
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 113 Solved: 24 SubmitStatusWeb Board Description ...
- [SDOI2010]所驼门王的宝藏
题目描述 在宽广的非洲荒漠中,生活着一群勤劳勇敢的羊驼家族.被族人恭称为"先知"的Alpaca L. Sotomon是这个家族的领袖,外人也称其为"所驼门王". ...
- [51nod1474]宝藏图
有n堆宝藏,每一堆宝藏有一个挖掘所需要的时间ti,有一个价值qi. 现在是做一个宝藏图.这个宝藏图是这样的,宝藏图的形状是一棵二叉树,二叉树刚好有k个叶子结点,从n堆宝藏中选k堆放到二叉树的叶子结点上 ...
随机推荐
- D题:数学题(贪心+二分)
原题大意:原题链接 题解链接 给定两个集合元素,求出两集合间任意两元素相除后得到的新集合中的第k大值 #include<cstdio> #include<algorithm> ...
- Educational Codeforces Round 56 Solution
A. Dice Rolling 签到. #include <bits/stdc++.h> using namespace std; int t, n; int main() { scanf ...
- c++第二十四天
p126~p128: 1.关系运算符作用于算数类型和指针类型. 2.逻辑运算符作用于任意能转换成布尔类型值的类型. 3.以上两种运算的运算对象和运算结果都是右值. 4.逻辑与和逻辑或的运算策略:短路求 ...
- bzoj1628 [Usaco2007 Demo]City skyline(单调栈)
Description Input 第一行给出N,W 第二行到第N+1行:每行给出二个整数x,y,输入的x严格递增,并且第一个x总是1 Output 输出一个整数,表示城市中最少包含的建筑物数量 Sa ...
- Stitching模块中focalsFromHomography初步研究
在Stitching模块中,通过“光束法平差”的时候,有一个步骤为“通过单应矩阵估算摄像头焦距”,调用的地方为: , )); ] ]; d2 ] ]) ] ]); v1 ] ] ...
- 20145122《Java程序设计》第一周学习总结
这周的JAVA学习开始了. 首先我了解JVM.JRE与JDK的区别与联系.JDK : (Java开发工具包).JDK是整个Java的核心,包括了Java运行环境JRE.Java工具和Java基础类库等 ...
- 在Github上搭建博客
貌似还是这个链接最靠谱呀 http://my.oschina.net/nark/blog/116299 如何利用github建立个人博客:之一 在线编辑器http://markable.in/ed ...
- python应用-掷骰子模拟-pygal
pygal安装: Linux下: pip install pygal Windows下: python -m pip install pygal 效果如图: # -*- coding: utf-8 - ...
- POJ Stockbroker Grapevine(floyd)
https://vjudge.net/problem/POJ-1125 题意: 题意不是很好理解,首先输入一个n,表示有n个股票经纪人,接下来输入n行,每行第一个数m为该股票经纪人认识的经纪人数,然后 ...
- mybatis 环境搭建和基本说明
mybatis介绍就不多提了,直接步入正题. 先准备好eclipse和MySQL,然后先看一下目录结构 文件和类很少,所以mybatis的搭建是非常简单的,如搭建中遇到问题可以先参考文档最后一部分的综 ...