【bzoj1040】[ZJOI2008]骑士 基环+外向树dp
2016-05-01 21:43
363 查看
这道题细节比较多。
我们可以把整个图分成若干个联通块,每个联通块都是一棵树+一条边。
对于每个联通块,我们找出环上的一条边(u,v),删去这条边,分别以u和v为根进行dp,最后把不取u和不取v中的最大值当做整个联通块的值。
最后的答案就是所有联通块的值的和。
注意处理重边的情况。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#define maxn 1000010
using namespace std;
int head[maxn],to[2*maxn],next[2*maxn],dep[maxn];
long long w[maxn],f[2][maxn];
bool vis[2][maxn];
int root1,root2,n,num;
long long ans=0;
void addedge(int x,int y)
{
num++;to[num]=y;next[num]=head[x];head[x]=num;
}
void dfs(int x,int fa)
{
for (int p=head[x];p;p=next[p])
if (to[p]!=fa)
{
if (dep[to[p]]) {root1=x;root2=to[p];continue;}
dep[to[p]]=dep[x]+1;
dfs(to[p],x);
}
}
void dp1(int x,int fa)
{
f[1][x]=w[x];f[0][x]=0;vis[0][x]=1;
for (int p=head[x];p;p=next[p])
if (to[p]!=fa && !vis[0][to[p]])
{
if ((x==root2 && to[p]==root1)) continue;
dp1(to[p],x);
f[1][x]+=f[0][to[p]];
f[0][x]+=max(f[0][to[p]],f[1][to[p]]);
}
}
void dp2(int x,int fa)
{
f[1][x]=w[x];f[0][x]=0;vis[1][x]=1;
for (int p=head[x];p;p=next[p])
if (to[p]!=fa && !vis[1][to[p]])
{
if ((x==root1 && to[p]==root2)) continue;
dp2(to[p],x);
f[1][x]+=f[0][to[p]];
f[0][x]+=max(f[0][to[p]],f[1][to[p]]);
}
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
long long x;
int y;
scanf("%lld%d",&x,&y);
w[i]=x;
addedge(i,y);addedge(y,i);
}
for (int i=1;i<=n;i++)
if (!vis[0][i])
{
dep[i]=1;dfs(i,0);
long long temp=0;
dp1(root1,0);temp=max(temp,f[0][root1]);
dp2(root2,0);temp=max(temp,f[0][root2]);
ans+=temp;
}
printf("%lld\n",ans);
return 0;
}
我们可以把整个图分成若干个联通块,每个联通块都是一棵树+一条边。
对于每个联通块,我们找出环上的一条边(u,v),删去这条边,分别以u和v为根进行dp,最后把不取u和不取v中的最大值当做整个联通块的值。
最后的答案就是所有联通块的值的和。
注意处理重边的情况。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#define maxn 1000010
using namespace std;
int head[maxn],to[2*maxn],next[2*maxn],dep[maxn];
long long w[maxn],f[2][maxn];
bool vis[2][maxn];
int root1,root2,n,num;
long long ans=0;
void addedge(int x,int y)
{
num++;to[num]=y;next[num]=head[x];head[x]=num;
}
void dfs(int x,int fa)
{
for (int p=head[x];p;p=next[p])
if (to[p]!=fa)
{
if (dep[to[p]]) {root1=x;root2=to[p];continue;}
dep[to[p]]=dep[x]+1;
dfs(to[p],x);
}
}
void dp1(int x,int fa)
{
f[1][x]=w[x];f[0][x]=0;vis[0][x]=1;
for (int p=head[x];p;p=next[p])
if (to[p]!=fa && !vis[0][to[p]])
{
if ((x==root2 && to[p]==root1)) continue;
dp1(to[p],x);
f[1][x]+=f[0][to[p]];
f[0][x]+=max(f[0][to[p]],f[1][to[p]]);
}
}
void dp2(int x,int fa)
{
f[1][x]=w[x];f[0][x]=0;vis[1][x]=1;
for (int p=head[x];p;p=next[p])
if (to[p]!=fa && !vis[1][to[p]])
{
if ((x==root1 && to[p]==root2)) continue;
dp2(to[p],x);
f[1][x]+=f[0][to[p]];
f[0][x]+=max(f[0][to[p]],f[1][to[p]]);
}
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
long long x;
int y;
scanf("%lld%d",&x,&y);
w[i]=x;
addedge(i,y);addedge(y,i);
}
for (int i=1;i<=n;i++)
if (!vis[0][i])
{
dep[i]=1;dfs(i,0);
long long temp=0;
dp1(root1,0);temp=max(temp,f[0][root1]);
dp2(root2,0);temp=max(temp,f[0][root2]);
ans+=temp;
}
printf("%lld\n",ans);
return 0;
}
相关文章推荐
- 读取Kafka集群的消息
- STL——vector和map
- 动态删除ArrayList中的元素
- Geekband009第九周笔记分享
- JAVA语言之计数排序
- JAVA中的集合的概念
- 找到满足条件的数组
- 第九章多态抽象
- codeforce 401C 构造
- 学习进度条
- 忘记oracle的sys用户密码怎么修改
- Java jvm 内存回收机制
- ARP协议工作原理
- Spring学习-helloworld
- ZOJ-3640 Help Me Escape (概率DP)
- 热门物联网开发平台
- [java]struts2 模型驱动
- hibernate多对一关联只映射出一张表
- 大数据处理
- spring与redis集成之aop整合方案