BZOJ 3037 创世纪

 

 题解:

 首先从基环树上的环上选两个点x,y

 断开x,y之间的边,然后做树形DP.

 设f[x]为选x的情况下的最大值,g[x]为不选x的情况下的最大值.

 分两种情况讨论,

 1.选x,则y一开始就处于被支配状态,在计算y的f[]函数值时需要特判.

 2.不选x,按正常DP做即可.

 

 1 #include<cstdio>
 2 #include<vector>
 3 using namespace std;
 4 #define ll long long
 5 #define FILE "dealing"
 6 #define up(i,j,n) for(int i=j;i<=n;i++)
 7 #define db long double 
 8 #define pii pair<int,int>
 9 #define pb push_back
10 #define mem(a,L) memset(a,0,sizeof(int)*(L+1))
11 template<class T> inline bool cmin(T& a,T b){return a>b?a=b,true:false;}
12 template<class T> inline bool cmax(T& a,T b){return a<b?a=b,true:false;}
13 template<class T> inline T squ(T a){return a*a;}
14 const ll maxn=2000100+10,inf=1e9+10,limit=1e7;
15 int read(){
16     int x=0,f=1,ch=getchar();
17     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
18     while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
19     return x*f;
20 }
21 int n;
22 vector<int> t[maxn];
23 int f[maxn],g[maxn],to[maxn];
24 int vis[maxn];
25 int rt,rt2,q[maxn],top=0;
26 void dfs(int x){
27     q[++top]=x;
28     vis[x]=1;
29     if(!vis[to[x]])dfs(to[x]);
30     else {
31         rt=x;
32         rt2=to[x];
33     }
34 }
35 void dfs2(int x){
36     vis[x]=1;
37     for(int i=0;i<t[x].size();i++)
38         if(!vis[t[x][i]])dfs2(t[x][i]);
39     if(!vis[to[x]])dfs2(to[x]);
40 }
41 //f[x] 选 g[x] 不选
42 int flag=0;
43 void dfs1(int x){//选rt
44     f[x]=1,g[x]=0;int Max=-inf;
45     for(int i=0;i<t[x].size();i++){
46         int y=t[x][i];if((x==rt2&&y==rt))continue;
47         dfs1(y);
48         f[x]+=f[y];
49         g[x]+=f[y];
50         cmax(Max,g[y]-f[y]);
51     }
52     f[x]+=Max;
53     if(x==rt2&&flag)f[x]-=Max;
54     cmax(f[x],0);
55 }
56 
57 int main(){
58     freopen(FILE".in","r",stdin);
59     freopen(FILE".out","w",stdout);
60     n=read();
61     up(i,1,n){
62         to[i]=read();
63         t[to[i]].push_back(i);
64     }
65     int ans=0;
66     up(i,1,n){
67         if(vis[i])continue;
68         top=0;dfs(i);
69         while(top)vis[q[top--]]=0;
70         dfs2(i);
71         int Ans=0;
72         flag=1;
73         dfs1(rt);
74         cmax(Ans,g[rt]);
75         flag=0;
76         dfs1(rt);
77         cmax(Ans,f[rt]);
78         ans+=Ans;
79     }
80     printf("%d\n",ans);
81     return 0;
82 }
View Code

 

posted @ 2017-05-04 15:20  CHADLZX  阅读(176)  评论(0编辑  收藏  举报