码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ1040 [ZJOI2008]骑士

时间:2015-03-17 21:32:32      阅读:132      评论:0      收藏:0      [点我收藏+]

标签:

首先,建出来的是无向图,因为a看不上b他们一定不会一起被选出。。。

然后,n个点n条边,形成的是环套树森林

于是有个奇技淫巧的做法,先dfs一遍找到环上的两个点,然后拆掉那条边,记下来边的两端x, y两个节点

强制x为根且x不选做树形动规,然后强制y为根且y不选再做一遍树形动规,两次的最大值加入答案

注意写法,我记录了father就找不到二元环的情况了QAQQQ,WA到死。。。要记录来的那条边

 

技术分享
 1 /**************************************************************
 2     Problem: 1040
 3     User: rausen
 4     Language: C++
 5     Result: Accepted
 6     Time:1992 ms
 7     Memory:51724 kb
 8 ****************************************************************/
 9  
10 #include <cstdio>
11 #include <algorithm>
12  
13 using namespace std;
14 const int N = 1e6 + 5;
15  
16 struct edge {
17     int next, to, f;
18     edge() {}
19     edge(int _n, int _t, int _f = 1) : next(_n), to(_t), f(_f) {}
20 } e[N << 1];
21  
22 int n, rt1, rt2;
23 int first[N], tot = 1;
24 int v[N], vis[N];
25 long long f[N][2], ans;
26  
27 inline int read() {
28     int x = 0;
29     char ch = getchar();
30     while (ch < 0 || 9 < ch)
31         ch = getchar();
32     while (0 <= ch && ch <= 9) {
33         x = x * 10 + ch - 0;
34         ch = getchar();
35     }
36     return x;
37 }
38  
39 inline void Add_Edges(int x, int y) {
40     e[++tot] = edge(first[x], y), first[x] = tot;
41     e[++tot] = edge(first[y], x), first[y] = tot;
42 }
43  
44 #define y e[x].to
45 void dfs(int p, int from) {
46     int x;
47     vis[p] = 1;
48     for (x = first[p]; x; x = e[x].next) 
49         if (!vis[y]) dfs(y, x);
50         else if ((from ^ 1) != x && !rt1)
51             rt1 = p, rt2 = y, e[x].f = e[x ^ 1].f = 0;
52 }
53  
54 void dp(int p, int t) {
55     int x;
56     vis[p] = t;
57     f[p][0] = 0, f[p][1] = v[p];
58     for (x = first[p]; x; x = e[x].next)
59         if (vis[y] != t && e[x].f) {
60             dp(y, t);
61             f[p][0] += max(f[y][0], f[y][1]);
62             f[p][1] += f[y][0];
63         }
64 }
65 #undef y
66  
67 int main() {
68     int i;
69     long long tmp;
70     n = read();
71     for (i = 1; i <= n; ++i)
72         v[i] = read(), Add_Edges(read(), i);
73     for (i = 1; i <= n; ++i)
74         if (!vis[i]) {
75             rt1 = rt2 = 0;
76             dfs(i, 0);
77             dp(rt1, 2), tmp = f[rt1][0];
78             dp(rt2, 3), ans += max(tmp, f[rt2][0]);
79         }
80     printf("%lld\n", ans);
81     return 0;
82 }
View Code

 

BZOJ1040 [ZJOI2008]骑士

标签:

原文地址:http://www.cnblogs.com/rausen/p/4345378.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!