[bzoj1040][ZJOI2008]骑士(树上dp)
2016-07-19 14:47
363 查看
【题目链接】http://www.lydsy.com/JudgeOnline/problem.php?id=1040
【题目大意】每个人有战斗力和一个痛恨的人,他不能与那个人一起出征,求最大战斗力总和
【解题思路】整体的图由一个或多个联通块构成。每个联通块点数等于边数。由于每个点至少连一条边所以这是一个环套树(在一棵树上加一条边构成的图)。dfs随意拆环,按被拆边两个端点的选取情况进行两次dp择优作为此联通块答案。
【呆马】
【题目大意】每个人有战斗力和一个痛恨的人,他不能与那个人一起出征,求最大战斗力总和
【解题思路】整体的图由一个或多个联通块构成。每个联通块点数等于边数。由于每个点至少连一条边所以这是一个环套树(在一棵树上加一条边构成的图)。dfs随意拆环,按被拆边两个端点的选取情况进行两次dp择优作为此联通块答案。
【呆马】
#include<cstdio> #include<algorithm> #include<cmath> #include<cstdlib> #include<iostream> #define ll long long const int N=1e6+1; using namespace std; struct st{int to,next,op;} e[N<<1]; int n,i,x,p,q,ed1,ed2,cnt,fi ,v ; ll t,ans,f [2]; bool vis ; void add(int x,int y) { e[++cnt].to=y; e[cnt].next=fi[x]; e[cnt].op=cnt+1; fi[x]=cnt; e[++cnt].to=x; e[cnt].next=fi[y]; e[cnt].op=cnt-1; fi[y]=cnt; } void dfs(int x,int fa) { vis[x]=1; for (int i=fi[x];i;i=e[i].next) if (e[i].to!=fa) { if (vis[e[i].to]) p=x,q=e[i].to,ed1=i,ed2=e[i].op; else dfs(e[i].to,x); } } void dp(int x,int fa) { f[x][0]=0; f[x][1]=v[x]; for (int i=fi[x];i;i=e[i].next) if (i!=ed1 && i!=ed2 && e[i].to!=fa) { int y=e[i].to; dp(y,x); f[x][0]+=max(f[y][0],f[y][1]); f[x][1]+=f[y][0]; } } int main() { scanf("%d\n",&n); for (i=1;i<=n;i++) { scanf("%d%d\n",&v[i],&x); add(i,x); } for (i=1;i<=n;i++) if (!vis[i]) { p=q=0; dfs(i,0); dp(p,0); t=f[p][0]; dp(q,0); ans+=max(t,f[q][0]); } printf("%lld",ans); }
相关文章推荐
- BZOJ3275 Number (最小割)
- BZOJ2809——[Apio2012]dispatching
- BZOJ2809——[Apio2012]dispatching
- [bzoj1003] [ZJOI2006]物流运输trans
- [bzoj1500][NOI2005]维修数列
- [bzoj1208] [HNOI2004]宠物收养所
- [bzoj1269][AHOI2006]文本编辑器editort
- [bzoj1503][NOI2004]郁闷的出纳员
- bzoj4305 数学
- bzoj3926 广义后缀自动机
- bzoj2780 广义后缀自动机+parent树+Dfs序+树状数组
- BZOJ1997 2-sat
- bzoj4027 贪心
- [BZOJ2038][2009国家集训队][莫队][分块]小z的袜子
- [BZOJ2594][WC2006][LCT][MST]水管局长数据加强版
- [BZOJ2300][HAOI2011][动态凸包]防线修建
- [BZOJ1045][HAOI2008][贪心]糖果传递
- [BZOJ2539][CTSC2000][KM]丘比特的烦恼
- [BZOJ1004][HNOI2008][Burnside引理][DP]Cards
- [BZOJ1202][HNOI2005][并查集]狡猾的商人