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;
}

 

posted @ 2018-12-03 19:36  Bruce--Wang  阅读(152)  评论(0编辑  收藏  举报