BZOJ1040 骑士
2016-07-16 18:58
435 查看
传送门
2≤n≤106,1≤vali≤106.
好像什么都不用讲吧
首先可以把图中的边看作无向边,因为每个点都存在至少一条边与它相关联,所以整个图肯定是由若干基环外向树形成的.
参考了LIN452的一种简单的写法,先用并查集找出会形成环的边,然后把这条边断掉,枚举这两个点中哪一个不取(也包含了两个都不取的情况),都做一遍树上的最大独立集即可.
复杂度O(n).
题目大意
有n名骑士,每个人都有一个战斗力vali和一个讨厌的骑士(不是他自己),从其中选出若干骑士,使得对于选出的每个骑士,他所讨厌的骑士都没有被选出,求选出的骑士的战斗力之和的最大值.2≤n≤106,1≤vali≤106.
题解
经典的基环外向树上dp求最大独立集.好像什么都不用讲吧
首先可以把图中的边看作无向边,因为每个点都存在至少一条边与它相关联,所以整个图肯定是由若干基环外向树形成的.
参考了LIN452的一种简单的写法,先用并查集找出会形成环的边,然后把这条边断掉,枚举这两个点中哪一个不取(也包含了两个都不取的情况),都做一遍树上的最大独立集即可.
复杂度O(n).
代码
#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<<endl using 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 ,tot_edge,head ,par ; ll dp[2] ; pii edge[N<<1],loop ; 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 */
相关文章推荐
- 详解Android应用中屏幕尺寸的获取及dp和px值的转换
- 基于Android中dp和px之间进行转换的实现代码
- Android中dip、dp、sp、pt和px的区别详解
- LFC1.0.0 版本发布
- Android dpi,dip,dp的概念以及屏幕适配
- Android px、dp、sp之间相互转换
- HP data protector软件学习1--基本角色与基本工作流程
- HP data protector软件学习2--软件组成与界面介绍
- android中像素单位dp、px、pt、sp的比较
- Android对px和dip进行尺寸转换的方法
- Android根据分辨率进行单位转换-(dp,sp转像素px)
- android 尺寸 dp,sp,px,dip,pt详解
- DP问题各种模型的状态转移方程
- POJ-1695-Magazine Delivery-dp
- nyoj-1216-整理图书-dp
- TYVJ1193 括号序列解题报告
- 对DP的一点感想
- TYVJ上一些DP的解题报告
- soj1005. Roll Playing Games
- 01背包问题