BZOJ1040 骑士
来源:互联网 发布:linux进入命令模式 编辑:程序博客网 时间:2024/06/10 03:29
传送门
题目大意
有
题解
经典的基环外向树上dp求最大独立集.
好像什么都不用讲吧
首先可以把图中的边看作无向边,因为每个点都存在至少一条边与它相关联,所以整个图肯定是由若干基环外向树形成的.
参考了LIN452的一种简单的写法,先用并查集找出会形成环的边,然后把这条边断掉,枚举这两个点中哪一个不取(也包含了两个都不取的情况),都做一遍树上的最大独立集即可.
复杂度
代码
#include <cstdio>#include <cmath>#include <ctime>#include <cctype>#include <cstring>#include <cstdlib>#include <cassert>#include <set>#include <map>#include <queue>#include <vector>#include <bitset>#include <complex>#include <iostream>#include <algorithm>#define fi first#define se second#define pb push_back#define y1 kjfasiv#define lowbit(x) (x&-x)#define debug(x) cout<<#x<<"="<<x<<endlusing namespace std;typedef long long ll;typedef unsigned long long ull;typedef pair<int,int> pii;typedef pair<ll,ll> pll;const int mod=(int)1e9+7,INF=0x7fffffff,rx[]={-1,0,1,0},ry[]={0,1,0,-1};const double pi=acos(-1.0),eps=1e-8;template<class T>void rd(T &res){ res=0; char c; while(c=getchar(),c<48); do res=(res<<3)+(res<<1)+(c^48); while(c=getchar(),c>47);}template<class T>inline void Max(T &a,T b){ if(b>a)a=b;}template<class T>inline void Min(T &a,T b){ if(b<a)a=b;}inline void mod_add(int &a,int b){ if((a+=b)>=mod)a-=mod;}const int N=(int)1e6+5;int val[N],tot_edge,head[N],par[N];ll dp[2][N];pii edge[N<<1],loop[N];inline void add_edge(int u,int v){ edge[tot_edge]=pii(v,head[u]); head[u]=tot_edge++;}int get_root(int x){ return par[x]==x?x:par[x]=get_root(par[x]);}inline bool same(int u,int v){ return get_root(u)==get_root(v);}void unite(int u,int v){ u=get_root(u); v=get_root(v); par[u]=v;}void DP(int cur,int par=0){ dp[0][cur]=0; dp[1][cur]=val[cur]; for(int i=head[cur];~i;i=edge[i].se){ int son=edge[i].fi; if(son==par)continue; DP(son,cur); dp[0][cur]+=max(dp[0][son],dp[1][son]); dp[1][cur]+=dp[0][son]; }}int main(){ int n,tot_loop=0; rd(n); for(int i=1;i<=n;++i) head[par[i]=i]=-1; for(int i=1,tar;i<=n;++i){ rd(val[i]);rd(tar); if(same(i,tar))loop[tot_loop++]=pii(i,tar); else{ unite(i,tar); add_edge(i,tar); add_edge(tar,i); } } ll ans=0; for(int i=0;i<tot_loop;++i){ DP(loop[i].fi); ll tmp=dp[0][loop[i].fi]; DP(loop[i].se); ans+=max(tmp,dp[0][loop[i].se]); } printf("%lld\n",ans); return 0;}/* Jul.16.16 Tags:dp Submissions:1 Memory 52184kb Time 2008ms Code Length 2325B*/
0 0
- BZOJ1040 骑士
- BZOJ1040 [ZJOI2008]骑士
- 【bzoj1040】【ZJOI2008】【骑士】
- bzoj1040: [ZJOI2008]骑士 dp
- [BZOJ1040][ZJOI2008]骑士
- bzoj1040&CodeVS1423 骑士
- bzoj1040 骑士 树形dp
- BZOJ1040: [ZJOI2008]骑士
- bzoj1040 [ZJOI2008]骑士
- BZOJ1040: [ZJOI2008]骑士
- bzoj1040: [ZJOI2008]骑士
- bzoj1040: [ZJOI2008]骑士
- bzoj1040 [ZJOI2008]骑士
- BZOJ1040 [ZJOI2008]骑士
- [BZOJ1040]ZJOI2008 骑士|环套树DP
- BZOJ1040 洛谷 P2607 [ZJOI2008]骑士
- BZOJ1040 骑士 【环套树 树形dp】
- BZOJ1040 [ZJOI2008]骑士 环套树/dp
- 调整数组顺序使奇数位于偶数前面
- 如何在eclipse的配置文件里指定jdk路径
- LintCode:排序列表转换为二分查找树
- 4.FloatingActionButton
- C++中基类和派生类之间的转换实例
- BZOJ1040 骑士
- 链表中倒数第k个结点
- 5.Snackbar
- LeetCode 198. House Robber
- Linux学习笔记--打包压缩命令
- C++中多态的实现原理
- 6.CardView
- MySql 64位 windows下环境配置
- 自定义控件三部曲之动画篇(一)——alpha、scale、translate、rotate、set的xml属性及用法