对于hdu-5834MagicboyBiLuowithhisexcitedtree树形dp感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解theboysawthemanwithatelesc
对于hdu-5834 Magic boy Bi Luo with his excited tree 树形dp感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解the boy saw the man with a telescope树形图,并且为您提供关于C. Ilya And The Tree 树形dp 暴力、CCPC 2017 哈尔滨 L. Color a Tree && HDU 6241(二分+树形DP)、cf 627 F. Maximum White Subtree【树形dp】、Codeforces 1092F Tree with Maximum Cost(树形DP)的宝贵知识。
本文目录一览:- hdu-5834 Magic boy Bi Luo with his excited tree 树形dp(the boy saw the man with a telescope树形图)
- C. Ilya And The Tree 树形dp 暴力
- CCPC 2017 哈尔滨 L. Color a Tree && HDU 6241(二分+树形DP)
- cf 627 F. Maximum White Subtree【树形dp】
- Codeforces 1092F Tree with Maximum Cost(树形DP)
hdu-5834 Magic boy Bi Luo with his excited tree 树形dp(the boy saw the man with a telescope树形图)
http://acm.hdu.edu.cn/showproblem.php?pid=5834
神级烦的一个树形dp
dp1【0】【x】代表从x结点向下走并且回到x结点的最大值
dp1【1】【x】代表从x结点向下走,并且不回到x结点的最大值(去向某一个子树分支,通过index【x】记录)
dp1【1】【x】代表从x结点向下走,并且不回到x结点的第二大值
dp2【0】【x】代表从x结点向父节点走,并且回来的最大值
dp2【1】【x】代表从x结点向父节点走,并且不回来的最大值
带了几个调试时举得样例
#include<bits/stdc++.h> using namespace std; const int maxn=200005; const int inf=0x3f3f3f3f; long long dp1[3][maxn]; long long index[maxn]; long long dp2[2][maxn]; long long ans[maxn]; struct node { int ne,cost; }; int n; int v[maxn]; vector<node>w[maxn]; void dfs1(int x,int fa) { dp1[0][x]=v[x]; for(int i=0;i<w[x].size();i++) { node ne=w[x][i]; if(ne.ne==fa) continue; dfs1(ne.ne,x); if(dp1[0][ne.ne]-2*ne.cost>0) dp1[0][x]+=dp1[0][ne.ne]-2*ne.cost; } dp1[2][x]=dp1[1][x]=dp1[0][x]; for(int i=0;i<w[x].size();i++) { node ne=w[x][i]; if(ne.ne==fa) continue; int Now=dp1[0][x]-max(dp1[0][ne.ne]-2*ne.cost,0ll)+dp1[1][ne.ne]-ne.cost; if(Now>=dp1[1][x]) { dp1[2][x]=dp1[1][x]; index[x]=ne.ne; dp1[1][x]=Now; } else if(Now>=dp1[2][x]) { dp1[2][x]=Now; } } } void dfs2(int x,int fa) { int i,k; for(i=0;i<w[x].size();i++) { node ne=w[x][i]; if(ne.ne==fa) continue; int self=dp1[0][ne.ne]-2*ne.cost; if(self<0) self=0; dp2[0][ne.ne]=max(dp2[0][ne.ne],dp1[0][x]-self+dp2[0][x]-2*ne.cost); if(ne.ne==index[x]) { dp2[1][ne.ne]=max(dp2[1][ne.ne],dp2[0][x]-ne.cost+dp1[2][x]-self); } else { dp2[1][ne.ne]=max(dp2[1][ne.ne],dp2[0][x]-ne.cost+dp1[1][x]-self); } dp2[1][ne.ne]=max(dp2[1][ne.ne],dp1[0][x]-self+dp2[1][x]-ne.cost); dfs2(ne.ne,x); } } int main() { int tca=1,T,i; cin>>T; while(T--) { scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d",&v[i]); } int u1,u2,c; for(i=1;i<n;i++) { scanf("%d %d %d",&u1,&u2,&c); node tt; tt.ne=u2; tt.cost=c; w[u1].push_back(tt); tt.ne=u1; w[u2].push_back(tt); } printf("Case #%d:\n",tca++); for(i=0;i<=n;i++) dp1[0][i]=dp1[1][i]=dp1[2][i]=dp2[0][i]=dp2[1][i]=0,index[i]=-1; /* node tt; tt.ne=1; v[0]=0; tt.cost=0; w[0].push_back(tt); dfs1(0,0); dfs2(0,0);*/ dfs1(1,0); dfs2(1,0); for(i=1;i<=n;i++) { // cout<<dp1[0][i]<<" "<<dp1[1][i]<<" "<<dp2[0][i]<<" "<<dp2[1][i]<<endl; printf("%d\n",max(dp1[0][i]+dp2[1][i],dp1[1][i]+dp2[0][i])); } for(i=0;i<=n;i++) w[i].clear(); } return 0; } /* 5 2 6 3 3 4 1 2 5 1 3 1 1 4 4 1 5 2 5 3 3 3 3 3 1 2 1 1 3 1 1 4 1 1 5 1 10 2 2 2 2 2 2 2 4 4 4 1 2 1 2 3 1 2 4 1 2 5 1 2 6 1 1 7 5 7 8 1 7 9 1 7 10 1 */
C. Ilya And The Tree 树形dp 暴力
C. Ilya And The Tree
写法还是比较容易想到,但是这么暴力的写法不是那么的敢写。
就直接枚举了每一个点上面的点的所有的情况,对于这个点不放进去特判一下,然后排序去重提高效率。
注意dp[v]一开始存的是从根节点到这个节点都选的情况,这样才好往后转移。
#include <iostream> #include <cstdio> #include <algorithm> #include <vector> #include <cstring> #define inf 0x3f3f3f3f using namespace std; const int maxn = 4e5 + 10; typedef long long ll; int dp[maxn],head[maxn],cnt = 0,a[maxn]; vector<int>vec[maxn]; struct node { int u,v,nxt; node(int u=0,int v=0,int nxt=0):u(u),v(v),nxt(nxt){} }ex[maxn]; void init() { memset(head,-1,sizeof(head)); cnt = 0; } void add(int u,int v) { ex[cnt] = node(u,head[u]); head[u] = cnt++; ex[cnt] = node(v,u,head[v]); head[v] = cnt++; } int gcd(int a,int b) { return b == 0 ? a : gcd(b,a%b); } void dfs(int u,int pre) { for(int i=head[u];i!=-1;i=ex[i].nxt) { int v = ex[i].v; if (v == pre) continue; dp[v] = gcd(dp[u],a[v]); vec[v].push_back(dp[u]); for(int j=0;j<vec[u].size();j++) vec[v].push_back(gcd(vec[u][j],a[v])); sort(vec[v].begin(),vec[v].end()); vec[v].erase(unique(vec[v].begin(),vec[v].end()),vec[v].end()); dfs(v,u); } } int main() { init(); int n; scanf("%d",&n); for (int i = 1; i <= n; i++) scanf("%d",&a[i]); for(int i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); add(u,v); } dp[1] = a[1]; vec[1].push_back(0); dfs(1,-1); for (int i = 1; i <= n; i++) dp[i] = max(dp[i],vec[i].back()); for (int i = 1; i <= n; i++) printf("%d ",dp[i]); return 0; }
CCPC 2017 哈尔滨 L. Color a Tree && HDU 6241(二分+树形DP)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6241
题意:给你一棵有 n 个结点的树,每个结点初始颜色都为白色,有 A 个条件:结点 x_i 的黑色结点数目不少于 y_i 个,同时有 B 个条件,除了结点 x_j 及其子树外至少有 y_j 个结点,求把最少要染成黑色结点的数目使得满足 A + B 个条件。
题解:参考自:https://blog.csdn.net/u013534123/article/details/78523559
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <bitset>
using namespace std;
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<int,int>
#define pII pair<ll,ll>
#define pi acos(-1)
#define pb push_back
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int MAXN = 1e5 + 10;
const int MAXM = 1e6 + 10;
int n;
vector<int>vec[MAXN];
int siz[MAXN],b[MAXN],mn[MAXN],mx[MAXN];
int up[MAXN],down[MAXN];
void init() {
for(int i = 0; i <= n; i++) {
vec[i].clear();
b[i] = mn[i] = 0;
}
}
void getsize(int u,int fa) {
siz[u] = 1;
for(int i = 0; i < vec[u].size(); i++) {
int v = vec[u][i];
if(v == fa) continue;
getsize(v,u);
siz[u] += siz[v];
}
}
bool dfs(int u,int fa) {
int l = 0, r = 1;
for(int i = 0; i < vec[u].size(); i++) {
int v = vec[u][i];
if(v == fa) continue;
if(!dfs(v,u)) return false;
l += down[v], r += up[v];
}
down[u] = max(l, mn[u]), up[u] = min(r, mx[u]);
return down[u] <= up[u];
}
bool check(int x) {
for(int i = 1; i <= n; i++) {
mx[i] = min(x - b[i],siz[i]);
if(mx[i] < 0) return false;
}
return dfs(1,0) && down[1] <= x && x <= up[1];
}
int main() {
#ifdef local
freopen("data.txt", "r", stdin);
#endif
int t;
scanf("%d",&t);
while(t--) {
scanf("%d",&n);
init();
for(int i = 1; i < n; i++) {
int u,v;
scanf("%d%d",&u,&v);
vec[u].pb(v);
vec[v].pb(u);
}
getsize(1,0);
int m;
bool flag = true;
scanf("%d",&m);
while(m--) {
int x,y;
scanf("%d%d",&x,&y);
mn[x] = max(mn[x],y);
if(y > siz[x]) flag = false;
}
scanf("%d",&m);
while(m--) {
int x,y;
scanf("%d%d",&x,&y);
b[x] = max(b[x],y);
if(y > n - siz[x]) flag = false;
}
if(!flag) {
puts("-1");
continue;
}
int l = 0, r = n, ans = -1;
while(l <= r) {
int mid = (l + r) >> 1;
if(check(mid)) ans = mid, r = mid - 1;
else l = mid + 1;
}
printf("%d\n",ans);
}
return 0;
}
cf 627 F. Maximum White Subtree【树形dp】
思路
令黑点点权为 -1 , 白点点权为 1,求最大子树点权和。
设 f[i] 为包含 i 点的最大子树点权值,如果当前点的最大点权和 比 当前点父亲的最大点权和小, 则更新当前点。
比较蠢的做法是,分两种情况讨论下,当前点的点权和 大于 或 小于 0 的情况处理是不同的。
如果当前点子树权值 >= 0,且父亲的子树权值更大,应该把父亲点的子树归并到当前点的子树中。
如果当前点子树权值 < 0,且父亲的子树中白的比黑的多,就把父亲点的子树归并到当前点子树上。
CODE
Codeforces 1092F Tree with Maximum Cost(树形DP)
题目链接:Tree with Maximum Cost
题意:给定一棵树,树上每个顶点都有属性值ai,树的边权为1,求$\sum\limits_{i = 1}^{n} dist(i, v) \cdot a_i$,$dist(i, v) $为顶点i到顶点v的距离。该顶点v可以任意选择。
题解:O(n^2)的做法:从每个顶点跑一遍DFS,计算贡献值,并更新答案。(超时)
我们可以先计算出从顶点1跑的答案,发现顶点之间贡献的转移为$ans[u]=ans[fa]+(all-sum[u])-sum[u]$。(all为$\sum\limits_{i = 1}^{n} a_i$)
该顶点的上半部分贡献值增加(all-sum[u]),下半部分贡献值减少(sum[u])。


1 #include <set>
2 #include <map>
3 #include <queue>
4 #include <deque>
5 #include <stack>
6 #include <cmath>
7 #include <cstdio>
8 #include <vector>
9 #include <string>
10 #include <cstring>
11 #include <fstream>
12 #include <iostream>
13 #include <algorithm>
14 using namespace std;
15
16 #define eps 1e-8
17 #define pb push_back
18 #define PI acos(-1.0)
19 #define INF 0x3f3f3f3f
20 #define clr(a,b) memset(a,b,sizeof(a)
21 #define bugc(_) cerr << (#_) << " = " << (_) << endl
22 #define FAST_IO ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL)
23
24 const int N=2e5+10;
25 typedef long long ll;
26 typedef unsigned long long ull;
27 ll a[N],sum[N],res,cnt,ans[N];
28
29 vector <int> E[N];
30
31 void dfs(int u,int fa,ll len){
32 res+=len*a[u];
33 sum[u]=a[u];
34 for(int i=0;i<E[u].size();i++){
35 int v=E[u][i];
36 if(v==fa) continue;
37 dfs(v,u,len+1);
38 sum[u]+=sum[v];
39 }
40 }
41
42 void DFS(int u,int fa){
43 if(fa!=0) ans[u]=ans[fa]+cnt-2*sum[u];
44 for(int i=0;i<E[u].size();i++){
45 int v=E[u][i];
46 if(v==fa) continue;
47 DFS(v,u);
48 }
49 }
50
51 int main(){
52 FAST_IO;
53 int n;
54 cin>>n;
55 for(int i=1;i<=n;i++) cin>>a[i],cnt+=a[i];
56 for(int i=1;i<n;i++){
57 int u,v;
58 cin>>u>>v;
59 E[u].push_back(v);
60 E[v].push_back(u);
61 }
62 dfs(1,0,0);
63 ans[1]=res;
64 DFS(1,0);
65 cout<<*max_element(ans+1,ans+1+n)<<endl;
66 return 0;
67 }
我们今天的关于hdu-5834 Magic boy Bi Luo with his excited tree 树形dp和the boy saw the man with a telescope树形图的分享就到这里,谢谢您的阅读,如果想了解更多关于C. Ilya And The Tree 树形dp 暴力、CCPC 2017 哈尔滨 L. Color a Tree && HDU 6241(二分+树形DP)、cf 627 F. Maximum White Subtree【树形dp】、Codeforces 1092F Tree with Maximum Cost(树形DP)的相关信息,可以在本站进行搜索。
本文标签: