BZOJ 1040 骑士

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1040

题意:给出一个图,只有一个环。每个点有一个权值。选出一些点两两不相邻,使得权值最大?

图中只有一个环,那么我们先建树,那么只有一条非树边,非树边上两个点我们设为node和root,那么我们DP两边,先让node不能选,然后让root不能选,DP两次即可,而且,环边不能走。

 1 #include<algorithm>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<iostream>
 6 #define ll long long
 7 int tot,go[2000005],next[2000005],first[1000005],b[2000005];
 8 int vis[1000005],root,tmp,node,flag,n;
 9 ll f[1000005][2],w[1000005];
10 void insert(int x,int y,int id){
11     tot++;
12     go[tot]=y;
13     next[tot]=first[x];
14     first[x]=tot;
15     b[tot]=id;
16 }
17 void add(int x,int y,int id){
18     insert(x,y,id);
19     insert(y,x,id);
20 }
21 void dfs(int x,int fa){
22     vis[x]=1;
23     for (int i=first[x];i;i=next[i]){
24         int pur=go[i];
25         if (pur==fa) continue;
26         if (vis[pur]){
27             root=pur;
28             node=x;
29             tmp=b[i];
30             continue;
31         }
32         dfs(pur,x);
33     }
34 }
35 void dp(int x,int fa){
36     f[x][0]=0;f[x][1]=0;
37     for (int i=first[x];i;i=next[i]){
38         int pur=go[i];
39         if (b[i]==tmp||pur==fa) continue;
40         dp(pur,x);
41         f[x][0]+=std::max(f[pur][0],f[pur][1]);
42         f[x][1]+=f[pur][0];
43     }
44     f[x][1]+=w[x];
45     if (flag==0&&x==root) f[x][1]=0;
46     if (flag==1&&x==node) f[x][1]=0;
47 }
48 int main(){
49     scanf("%d",&n);
50     int id=0;
51     for (int i=1;i<=n;i++){
52         int x;
53         scanf("%lld%d",&w[i],&x);
54         id++;
55         add(i,x,id);
56     }
57     ll ans=0;
58     ll Ans=0;
59     for (int i=1;i<=n;i++)
60      if (!vis[i]){
61        node=tmp=0;
62        dfs(i,0);
63        flag=1;
64        dp(root,0);
65        Ans=std::max(f[root][0],f[root][1]);
66        flag=0;
67        dp(root,0);
68        Ans=std::max(Ans,std::max(f[root][0],f[root][1]));
69        ans+=Ans;
70     }
71     printf("%lld",ans);
72 }

 

posted @ 2016-06-02 19:09  GFY  阅读(262)  评论(0编辑  收藏  举报