【问题描述】
Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英。他们劫富济贫,惩恶扬善,受到社会各界的赞扬。
最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争。战火绵延五百里,在和平环境中安逸了数百年的Z国又怎能抵挡的住Y国的军队。于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一个真龙天子的降生,带领正义打败邪恶。
骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一些矛盾。每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己),他是绝对不会与自己最厌恶的人一同出征的。
战火绵延,人民生灵涂炭,组织起一个骑士军团加入战斗刻不容缓!国王交给了你一个艰巨的任务,从所有的骑士中选出一个骑士军团,使得军团内没有矛盾的两人(不存在一个骑士与他最痛恨的人一同被选入骑士军团的情况),并且,使得这支骑士军团最具有战斗力。
为了描述战斗力,我们将骑士按照1至N编号,给每名骑士一个战斗力的估计,一个军团的战斗力为所有骑士的战斗力总和。
【输入文件】
输入文件knight.in第一行包含一个正整数N,描述骑士团的人数。
接下来N行,每行两个正整数,按顺序描述每一名骑士的战斗力和他最痛恨的骑士。
【输出文件】
输出文件knight.out应包含一行,包含一个整数,表示你所选出的骑士军团的战斗力。
思路:题目中所给的条件本质就是一个环上连出去很多个树 DP
1 #include<iostream>
2 #include<cstring>
3 #include<cmath>
4 #include<cstdio>
5 #include<algorithm>
6 using namespace std;
7 #define MAXN 1000001
8 struct node
9 {
10 int num;
11 bool w;
12 node *next;
13 };
14 pair<int,int> ring[MAXN];
15 node *graph[MAXN];
16 node memo[2*MAXN];
17 int Q_tree[MAXN],Q_circle[MAXN],d[MAXN],father[MAXN];
18 long long a[MAXN],num[MAXN][2],dp[MAXN][2];
19 int top=0,n;
20 bool use[MAXN];
21 void add(int x,int y)
22 {
23 node *p=&memo[top++];
24 p->num=y; p->next=graph[x]; p->w=1; graph[x]=p;
25 p=&memo[top++];
26 p->num=x; p->next=graph[y]; p->w=0; graph[y]=p;
27 }
28 int find_circle(int i)
29 {
30 bool w=0;
31 int left,right,u;
32 Q_circle[left=right=1]=i;
33 d[i]=1;
34 father[i]=0;
35 while(left<=right)
36 {
37 u=Q_circle[left];
38 for(node *p=graph[u];p;p=p->next)
39 if(p->w)
40 {
41 if(d[p->num]==0)
42 {
43 d[p->num]=d[u]+1;
44 father[p->num]=u;
45 Q_circle[++right]=p->num;
46 }
47 else
48 {
49 father[p->num]=u; w=1;
50 break;
51 }
52 }
53 if(w) break;
54 left++;
55 }
56 int j=u;
57 for(i=father[u];i!=u;i=father[i],j=father[j])
58 ring[i]=make_pair(j,father[i]);
59 ring[u]=make_pair(j,father[u]);
60 return u;
61 }
62 void solve_tree(int i)
63 {
64 int left,right,u,j;
65 memset(d,0,sizeof(d));
66 d[i]=1; use[i]=1;
67 Q_tree[left=right=1]=i;
68 father[i]=0;
69 while(left<=right)
70 {
71 u=Q_tree[left++];
72 for(node *p=graph[u];p;p=p->next)
73 if(p->num!=father[u])
74 {
75 if(u==i&&(ring[u].first==p->num||p->num==ring[u].second)) continue;
76 use[p->num]=1;
77 d[p->num]=d[u]+1;
78 father[p->num]=u;
79 Q_tree[++right]=p->num;
80 }
81 }
82 for(j=right;j>0;j--)
83 {
84 u=Q_tree[j];
85 num[u][0]=0;
86 num[u][1]=a[u];
87 for(node *p=graph[u];p;p=p->next)
88 if(p->num!=father[u])
89 {
90 if(u==i&&(ring[u].first==p->num||p->num==ring[u].second)) continue;
91 num[u][0]+=max(num[p->num][0],num[p->num][1]);
92 num[u][1]+=num[p->num][0];
93 }
94 }
95 }
96 long long dynamic(int i)
97 {
98 long long ans=0;
99 int j;
100 dp[i][0]=num[i][0]; dp[i][1]=num[i][1];
101 for(j=ring[i].first;j!=ring[i].second;j=ring[j].first)
102 {
103 dp[j][1]=dp[ring[j].second][0]+num[j][1];
104 dp[j][0]=max(dp[ring[j].second][0],dp[ring[j].second][1])+num[j][0];
105 }
106 ans=max(dp[ring[j].second][0],dp[ring[j].second][1])+num[j][0];
107 dp[i][0]=num[i][0]; dp[i][1]=num[i][0];
108 for(j=ring[i].first;j!=i;j=ring[j].first)
109 {
110 dp[j][1]=dp[ring[j].second][0]+num[j][1];
111 dp[j][0]=max(dp[ring[j].second][0],dp[ring[j].second][1])+num[j][0];
112 }
113 ans=max(ans,max(dp[ring[j].second][0],dp[ring[j].second][1]));
114 return ans;
115 }
116
117 long long solve(int i)
118 {
119 i=find_circle(i);
120 int j;
121 for(j=ring[i].first;j!=i;j=ring[j].first)
122 solve_tree(j);
123 solve_tree(j);
124 return dynamic(j);
125
126
127 }
128 int main()
129 {
130 freopen("knight.in","r",stdin);
131 freopen("knight.out","w",stdout);
132 memset(num,0,sizeof(num));
133 memset(use,0,sizeof(use));
134 scanf("%d",&n);
135 int i,x;
136 long long ans=0;
137 for(i=1;i<=n;i++)
138 {
139 scanf("%lld%d",a+i,&x);
140 add(i,x);
141 }
142 for(i=1;i<=n;i++)
143 if(!use[i])
144 ans+=solve(i);
145 printf("%lld\n",ans);
146 return 0;
147 }
148