codeforces 338(Div 2) B. Longtail Hedgehog 解题报告

题目链接:http://codeforces.com/problemset/problem/615/B

题目意思:要画一只 hedgehog,由 tail 和 spines 组成。我们要求得 beauty 最大值: tail * spines。

以下摘自 udon 原话,大家细细品味:(不一定是正确无误的哦,可能有误导他人成分。。。)

  1、对于所有点 x,求出 x 的度数 d[x],O(n+m)

  2、对于所有点 x,求出以点 x 为结尾的最长链长度 l[x],由于尾巴节点要求递增,符合DAG性质,从 1 点开始 BFS 就可以了,O(n+m)

  3、枚举所有 x,比较出 l[x] * d[x] 最大值,得出答案, O(n),总复杂度O(n+m)

  spines其实就是tail最后一个点的度数,也就是tail确定之后,spines就自然出来了(spines等价于度数)

  这句话主要是给我看的:我们不是要spines最优(我之前一直被这个变量迷惑了= =),而是要 tail * spines 最优

  以下也是他的话:

############################  听udon一席话,胜读十年书呢 ^_^

分享下捻尼题既思路,其实就系物理常用控制变量法:
1、发现最后答案 res = max(tails * spines),有两个变量
2、简化下问题,我先假设spines一定的情况下,答案貌似就系tails最大值,已经系经典题目了
但系甘样要枚举所有度数下的tails最优值,超时
3、我再假设tails不变,情况下,根据定义spines就系tails最后一个点既度数数,嗟系
tails可以确定spines,唔洗求最优值!!
4、甘样我地久唔洗枚举度数,枚举tails就可以了

#############################

(1) DP 版本

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <vector>
 7 using namespace std;
 8 
 9 typedef long long LL;
10 
11 const int maxn = 1e5 + 5;
12 vector<int> edge[maxn];
13 LL dp[maxn];
14 
15 int main()
16 {
17     #ifndef ONLINE_JUDGE
18         freopen("in.txt", "r", stdin);
19     #endif // ONLINE_JUDGE
20 
21     int n, m;
22     while (scanf("%d%d", &n, &m) != EOF) {
23 
24         int u, v;
25         for (int i = 0; i < m; i++) {
26             scanf("%d%d", &u, &v);
27             edge[u].push_back(v);
28             edge[v].push_back(u);
29         }
30         LL ans = -1;
31         for (int i = 1; i <= n; i++) {
32             dp[i] = 1;
33             sort(edge[i].begin(), edge[i].end());
34             for (int j = 0; j < edge[i].size(); j++) {
35                 if (edge[i][j] > i) continue;
36                 dp[i] = max(dp[i], dp[edge[i][j]]+1);
37             }
38             ans = max(ans, dp[i]*(int)edge[i].size());
39         }
40         printf("%lld\n", ans);
41         for (int i = 1; i <= n; i++) {
42             edge[i].clear();
43         }
44     }
45 
46     return 0;
47 }

 

(2)DFS版本(记忆化搜索)

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <vector>
 7 using namespace std;
 8 
 9 typedef long long LL;
10 
11 const int maxn = 1e5 + 5;
12 vector<int> edge[maxn];
13 int vis[maxn];
14 LL ans;
15 
16 int dfs(int st)
17 {
18     if (vis[st])
19         return vis[st];   // 记忆化搜索,避免超时
20     int ret = 0;    // 设为-1是错的,因为 st 编号的数可能前面根本没有比它小的数 
21     for (int i = 0; i < edge[st].size(); i++) {
22         if (edge[st][i] < st) {  // 求出以 st 之前的最长递增序列
23             ret = max(ret, dfs(edge[st][i]));
24         }
25     }
26     vis[st] = ret + 1;
27     return vis[st];
28 }
29 
30 
31 int main()
32 {
33     #ifndef ONLINE_JUDGE
34         freopen("in.txt", "r", stdin);
35     #endif // ONLINE_JUDGE
36 
37     int n, m;
38     while (scanf("%d%d", &n, &m) != EOF) {
39 
40         int u, v;
41         for (int i = 0; i < m; i++) {
42             scanf("%d%d", &u, &v);
43             edge[u].push_back(v);
44             edge[v].push_back(u);
45         }
46         memset(vis, 0, sizeof(vis));
47         ans = -1;
48         for (int i = 1; i <= n; i++) {
49             if (!vis[i]) {
50                 ans = max( ans, (LL)dfs(i)*(int)edge[i].size() );
51             }
52         }
53 
54         printf("%lld\n", ans);
55         for (int i = 1; i <= n; i++) {
56             edge[i].clear();
57         }
58     }
59 
60     return 0;
61 }

 

posted @ 2016-01-10 16:42  windysai  阅读(274)  评论(0编辑  收藏  举报