ZJOI2009 骑士
Z 国的骑士团是一个很有势力的组织,帮会中聚集了来自各地的精英。他们劫富济贫,惩恶扬善,受到了社会各界的赞扬。可是,最近发生了一件很可怕的事情:邪恶的 Y 国发起了一场针对 Z 国的侵略战争。战火绵延五百里,在和平环境中安逸了数百年的 Z 国又怎能抵挡得住 Y 国的军队。于是人们把所有希望都寄托在了骑士团身上,就像期待有一个真龙天子的降生,带领正义打败邪恶。骑士团是肯定具备打败邪恶势力的能力的,但是其实们互相之间往往有一些矛盾。每个骑士有且仅有一个他自己最厌恶的骑士(当然不是他自己),他是绝对不会与最厌恶的人一同出征的。战火绵延,人们生灵涂炭,组织起一个骑士军团加入战斗刻不容缓!国王交给你了一个艰巨的任务:从所有骑士中选出一个骑士军团,使得军内没有矛盾的两人,即不存在一个骑士与他最痛恨的人一同被选入骑士团的情况,并且使这支骑士军团最富有战斗力。为描述战斗力,我们将骑士按照 1 至 N 编号,给每位骑士估计一个战斗力,一个军团的战斗力为所有骑士的战斗力之和。
看似是树形DP,但是实际上就是树形DP
这道题是有环的,是一个基环树森林,每次DP的时候,把环上任意一条边删去,然后从和调边连接的两个点分别DP,要保证其中一个不选
然后取更优值,累加到答案中
判断环可以用并查集,然后DFS过程中连边
下面给出代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<string> #define max(a,b) a > b ? a : b using namespace std; inline long long rd(){ long long x=0,f=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; return x*f; } inline void write(long long x){ if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10+'0'); return ; } long long n; long long head[2000006]; long long to[2000006]; long long nxt[2000006]; long long total=0; long long v[2000006],x[2000006]; long long dp[1000006][2]; void add(long long x,long long y){ total++; to[total]=y; nxt[total]=head[x]; head[x]=total; return ; } long long f[1000006]; long long getf(long long v){ if(f[v]==v) return v; return f[v]=getf(f[v]); } long long merge(long long x,long long y){ if(getf(x)==getf(y)) return 1; f[getf(x)]=getf(y); return 0; } long long root1=0,root2=0; long long head2[2000006],to2[2000006]; long long nxt2[2000006]; long long total2=0; void solve(long long x,long long fa){ dp[x][0]=0;dp[x][1]=v[x]; for(long long e=head2[x];e;e=nxt2[e]){ if(to2[e]!=fa){ solve(to2[e],x); dp[x][1]+=dp[to2[e]][0]; dp[x][0]+=max(dp[to2[e]][0],dp[to2[e]][1]); } } return ; } long long book[1000006]; long long ff=0; void add2(long long x,long long y){ total2++; to2[total2]=y; nxt2[total2]=head2[x]; head2[x]=total2; return ; } void dfs(long long x,long long fa){ book[x]=1; for(long long e=head[x];e;e=nxt[e]){ if(to[e]!=fa){ if(merge(x,to[e])){ ff=1; root1=x; root2=to[e]; } else add2(x,to[e]),add2(to[e],x); if(book[to[e]]==0) dfs(to[e],x); } } return ; } int main(){ long long ans=0; n=rd(); for(long long i=1;i<=n;i++) f[i]=i; for(long long i=1;i<=n;i++){ v[i]=rd(),x[i]=rd(); add(x[i],i),add(i,x[i]); } for(long long i=1;i<=n;i++){ if(!book[i]){ ff=0; dfs(i,0); if(!ff){ solve(i,0); ans+=max(dp[i][0],dp[i][1]); } else{ solve(root1,0); long long set=dp[root1][0]; solve(root2,0); ans+=max(set,dp[root2][0]); } } } write(ans); return 0; }
(20行版本):
#include<algorithm> #include<cstdio> #include<string> #define max(a,b) a > b ? a : b using namespace std; inline long long rd(){long long x=0,f=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; return x*f;} inline void write(long long x){if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10+'0');} long long n,head[2000006],to[2000006],nxt[2000006],total=0,v[2000006],x[2000006],dp[1000006][2],f[1000006]; void add(long long x,long long y){total++;to[total]=y;nxt[total]=head[x];head[x]=total;} long long getf(long long v){return (f[v]==v)?v:f[v]=getf(f[v]);} long long merge(long long x,long long y){if(getf(x)==getf(y)) return 1;else f[getf(x)]=getf(y); return 0;} long long root1=0,root2=0,head2[2000006],to2[2000006],nxt2[2000006],total2=0,book[1000006],ff=0; void solve(long long x,long long fa){dp[x][0]=0;dp[x][1]=v[x];for(long long e=head2[x];e;e=nxt2[e]) if(to2[e]!=fa){solve(to2[e],x);dp[x][1]+=dp[to2[e]][0];dp[x][0]+=max(dp[to2[e]][0],dp[to2[e]][1]);}return ;} void add2(long long x,long long y){total2++;to2[total2]=y;nxt2[total2]=head2[x];head2[x]=total2;} void dfs(long long x,long long fa){book[x]=1;for(long long e=head[x];e;e=nxt[e]) if(to[e]!=fa){if(merge(x,to[e])) ff=1,root1=x,root2=to[e];else add2(x,to[e]),add2(to[e],x);if(book[to[e]]==0) dfs(to[e],x);}return ;} int main(){ long long ans=0,set=0;n=rd(); for(long long i=1;i<=n;i++) f[i]=i; for(long long i=1;i<=n;i++){v[i]=rd(),x[i]=rd();add(x[i],i),add(i,x[i]);} for(long long i=1;i<=n;i++) if(!book[i]){ff=0;dfs(i,0);if(!ff){solve(i,0);ans+=max(dp[i][0],dp[i][1]);continue;}solve(root1,0);set=dp[root1][0];solve(root2,0);ans+=max(set,dp[root2][0]);}write(ans); return 0; }
蒟蒻总是更懂你✿✿ヽ(°▽°)ノ✿