BZOJ 1040: [ZJOI2008]骑士 [DP 环套树]
题意:环套树的最大权独立集
一开始想处理出外向树树形$DP$然后找到环再做个环形$DP$
然后看了看别人的题解其实只要断开环做两遍树形$DP$就行了...有道理!
注意不连通
然后洛谷时限再次不科学,卡常失败$SAD$
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N=1e6+5; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } int n,val[N]; struct edge{ int v,ne; }e[N<<1]; int h[N],cnt=1; inline void ins(int u,int v){ cnt++; e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt; cnt++; e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt; } int a,b; bool vis[N],del[N<<1]; void dfs(int u,int fa){ vis[u]=1; for(int i=h[u];i;i=e[i].ne) if(e[i].v!=fa){ if(vis[e[i].v]) a=u,b=e[i].v,del[i]=del[i^1]=1; else dfs(e[i].v,u); } } ll f[N][2],ans; void dp(int u,int fa){ f[u][1]=val[u];f[u][0]=0; for(int i=h[u];i;i=e[i].ne) if(!del[i]&&e[i].v!=fa){ dp(e[i].v,u); f[u][1]+=f[e[i].v][0]; f[u][0]+=max(f[e[i].v][0],f[e[i].v][1]); } } int main(){ freopen("in","r",stdin); n=read(); for(int i=1;i<=n;i++) val[i]=read(),ins(i,read()); for(int i=1;i<=n;i++) if(!vis[i]){ dfs(i,0); dp(a,0); ll _=f[a][0]; dp(b,0); ans+=max(_,f[b][0]); } printf("%lld",ans); }
Copyright:http://www.cnblogs.com/candy99/