HDU 5834 Magic boy Bi Luo with his excited tree
2016-08-15 20:08
218 查看
题目:Magic boy Bi Luo with his excited tree
链接:http://acm.hdu.edu.cn/showproblem.php?pid=5834
题意:给一棵树,在树的每个结点可以收获一定的积分,每一条边会消耗一定的积分,每个结点积分取一次便完,但每次路过一条边,都会消耗积分,问从每一个结点出发,最多能捞多少积分。N范围10万,样例数1万。
思路:
不难的一道题,但细节较多,容易出错。
树形DP。
从i 点出发,大致可以分为向上 和 向下两种,先考虑向下的情况。可以想到,假设i 连着n 条边,那么如果要想把n 条边外的积分都拿到手,那么n 条边,有n-1 条边要走两次。那么,我们可以设置dp 如下:
dp[i]:从i 出发,又回到i 的最优解
fen[i][0]:从i 出发,不回到i 的最优解 ----- fen[i][1]:最终朝着哪个边离开
fen[i][2]:从i 出发,不回到i 的次优解
对i 结点,我们需要的信息就是上面4 个,一次dfs可以求出。
对根节点rt,他的答案ans[rt] = fen[rt][0]。对于中间的某个结点x,ans[x] 是两种情况取最大,一:从i 出发,往上方走,又回到i ,再往下方走(不回来了),其中往下方走不回来就是fen[x][0],往上方走又回来(暂放)。二:从i 出发,往下方走,又回到i ,再往上方走(不回来),这里往下方走又回来就是dp[x],往上方走不会来(暂放)。
上面这一步中dfs要传两个参数(up1,up2),up1表示往上方走不回来的最优解,up2表示往上方走又回来的最优解。现在我们来解决这两个参数,在x 点时,对于x 的某个孩子son ,e是x 和son 连接的边,假如这个son 就是fen[x][1],那么fen[x][2]-max(0,dp[son]-2*e)就代表了从x 出发,不往son 方向走又不回来的最优解,如果son 不是fen[x][1],那么这个最优解就是fen[x][0]-max(0,dp[son]-2*e),而up1代表了从x 出发,往上方走,不回来的最优解,那么要想两者都得到,要么往上方走回来(up2),要么往下方走回来(dp[x]-max(0,dp[son]-2*e)),这两个可以取最优解,就可以得到son 的up1、up2参数(up1要减去e,up2要减去2e)。
提供一组数据:
2
5
1 2 2 2 2
1 2 1
1 3 1
3 4 3
3 5 3
7
1 4 1 7 6 9 8
1 2 2
1 3 1
2 4 3
2 5 4
3 6 6
3 7 7
答案为:
1. 2 3 3 2 2
2. 7 8 7 10 10 10 8
我在倒二个10 弄了半天,一直显示9 ,搞了半天
AC代码:
链接:http://acm.hdu.edu.cn/showproblem.php?pid=5834
题意:给一棵树,在树的每个结点可以收获一定的积分,每一条边会消耗一定的积分,每个结点积分取一次便完,但每次路过一条边,都会消耗积分,问从每一个结点出发,最多能捞多少积分。N范围10万,样例数1万。
思路:
不难的一道题,但细节较多,容易出错。
树形DP。
从i 点出发,大致可以分为向上 和 向下两种,先考虑向下的情况。可以想到,假设i 连着n 条边,那么如果要想把n 条边外的积分都拿到手,那么n 条边,有n-1 条边要走两次。那么,我们可以设置dp 如下:
dp[i]:从i 出发,又回到i 的最优解
fen[i][0]:从i 出发,不回到i 的最优解 ----- fen[i][1]:最终朝着哪个边离开
fen[i][2]:从i 出发,不回到i 的次优解
对i 结点,我们需要的信息就是上面4 个,一次dfs可以求出。
对根节点rt,他的答案ans[rt] = fen[rt][0]。对于中间的某个结点x,ans[x] 是两种情况取最大,一:从i 出发,往上方走,又回到i ,再往下方走(不回来了),其中往下方走不回来就是fen[x][0],往上方走又回来(暂放)。二:从i 出发,往下方走,又回到i ,再往上方走(不回来),这里往下方走又回来就是dp[x],往上方走不会来(暂放)。
上面这一步中dfs要传两个参数(up1,up2),up1表示往上方走不回来的最优解,up2表示往上方走又回来的最优解。现在我们来解决这两个参数,在x 点时,对于x 的某个孩子son ,e是x 和son 连接的边,假如这个son 就是fen[x][1],那么fen[x][2]-max(0,dp[son]-2*e)就代表了从x 出发,不往son 方向走又不回来的最优解,如果son 不是fen[x][1],那么这个最优解就是fen[x][0]-max(0,dp[son]-2*e),而up1代表了从x 出发,往上方走,不回来的最优解,那么要想两者都得到,要么往上方走回来(up2),要么往下方走回来(dp[x]-max(0,dp[son]-2*e)),这两个可以取最优解,就可以得到son 的up1、up2参数(up1要减去e,up2要减去2e)。
提供一组数据:
2
5
1 2 2 2 2
1 2 1
1 3 1
3 4 3
3 5 3
7
1 4 1 7 6 9 8
1 2 2
1 3 1
2 4 3
2 5 4
3 6 6
3 7 7
答案为:
1. 2 3 3 2 2
2. 7 8 7 10 10 10 8
我在倒二个10 弄了半天,一直显示9 ,搞了半天
AC代码:
#include<stdio.h> #include<string.h> #include<vector> #include<algorithm> using namespace std; #define N 100010 vector<pair<int,int> > v ; int w ; //w[i] : 点i 的权值 int dp ; //dp[i] : 从i 往下走,又回到i 的最大收获 int fen [3]; /* fen[i][0] : 从i 出发,不回到i 的最大收获 fen[i][1] : 从i 出发,不回到i 的最大收获 的 最后路径(就是不重复两次的那条) fen[i][2] : 从i 出发,不回到i 的次大收获 */ void dfs(int rt,int fa) { dp[rt]=w[rt]; for(int i=0;i<v[rt].size();i++) { if(v[rt][i].first==fa) continue; dfs(v[rt][i].first,rt); dp[rt] += max(0 , dp[v[rt][i].first] - 2*v[rt][i].second); } fen[rt][1]=-1; fen[rt][0]=fen[rt][2]=w[rt]; for(int i=0;i<v[rt].size();i++) { int ad=v[rt][i].first; int wa=v[rt][i].second; if(ad==fa) continue; int now = dp[rt] - max(0 , dp[ad]-2*wa) + max(0 , fen[ad][0]-wa); // now 就是从这条路径出发不回来的收获 if(now>fen[rt][0]) { fen[rt][2]=fen[rt][0]; fen[rt][0]=now; fen[rt][1]=i; } else if(now>fen[rt][2]) fen[rt][2]=now; } } int ans ; void dfs2(int rt,int fa,int up1,int up2) {//up1 : rt父结点出去不回来的最优解 up2 : rt父结点出去又回到父结点的最优解 ans[rt]=max(dp[rt]+up1,up2+fen[rt][0]); for(int i=0;i<v[rt].size();i++) { int ad=v[rt][i].first; int wa=v[rt][i].second; if(ad==fa) continue; int down1,down2; if(fen[rt][1]==i) down1=max(0 , fen[rt][2] - max(0,dp[ad]-2*wa)); else down1=max(0 , fen[rt][0] - max(0,dp[ad]-2*wa)); down2=max(0 , dp[rt] - max(0,dp[ad]-2*wa)); down1=max(0 , max(up1+down2-wa,up2+down1-wa)); down2=max(0 , up2+down2-2*wa); dfs2(ad,rt,down1,down2); } } int main() { int t,n,x,y,z,cas=1; scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&w[i]); for(int i=1;i<n;i++) { scanf("%d%d%d",&x,&y,&z); v[x].push_back(make_pair(y,z)); v[y].push_back(make_pair(x,z)); } dfs(1,0); dfs2(1,0,0,0); printf("Case #%d:\n",cas++); for(int i=1;i<=n;i++) printf("%d\n",ans[i]); for(int i=1;i<=n;i++) v[i].clear(); } return 0; }
相关文章推荐
- hdu 5834 Magic boy Bi Luo with his excited tree 树形dp
- hdu 5834 Magic boy Bi Luo with his excited tree
- hdu 5834 Magic boy Bi Luo with his excited tree 树形dp
- HDU 5834 Magic boy Bi Luo with his excited tree 树形dp
- HDU 5834 Magic boy Bi Luo with his excited tree 树形DP ★ ★
- hdu 5834 Magic boy Bi Luo with his excited tree
- 【树形动规】HDU 5834 Magic boy Bi Luo with his excited tree
- HDU 5834 Magic boy Bi Luo with his excited tree (树形DP)
- CPPC网络选拔赛 C题 [HDU 5834] Magic boy Bi Luo with his excited tree (树形dp)
- hdu 5834 Magic boy Bi Luo with his excited tree (树形dp)
- HDU 5834 Magic boy Bi Luo with his excited tree(树形dp)
- HDU - 5834 Magic boy Bi Luo with his excited tree 树形dp 好题~
- hdu-5834 Magic boy Bi Luo with his excited tree 树形dp
- Hdu-5834 Magic boy Bi Luo with his excited tree(树形DP)
- HDU 5834 Magic boy Bi Luo with his excited tree 树形DP
- HDU 5834 Magic boy Bi Luo with his excited tree
- HDU 5834 Magic boy Bi Luo with his excited tree (树形DP)
- hdu-5834 Magic boy Bi Luo with his excited tree(树形dp)
- HDU - 5834 Magic boy Bi Luo with his excited tree 树形DP(经典)
- hdu 5834 Magic boy Bi Luo with his excited tree (树形dp)