题目链接: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) 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 ", 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 ", ans); 55 for (int i = 1; i <= n; i++) { 56 edge[i].clear(); 57 } 58 } 59 60 return 0; 61 }