1
斐波那契数列增长速度很快,在第45个的时候就已经超过了1000000000,只要开个45位的数组就差不多了,后面只要扫这个小数组判断是不是斐波那契数就行了
让u和v合并到同一个家族使用并查集,最后扫根节点找集合威望最大值
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <limits> #include <algorithm> using namespace std; struct node { int w; //用于存能给家族增加的威望值 int p; //存父节点 }; const int maxn = 45; int a[50]; node f[1005]; void fbb() { //斐波那契数列打表 a[1] = a[2] = 1; for (int i = 3; i <= maxn; i++) { a[i] = a[i - 1] + a[i - 2]; } } int getf(int v) { //得到v的根节点 if (f[v].p == v) { return v; } else { f[v].p = getf(f[v].p); //路径压缩 return f[v].p; } } void Merge(int u, int v) { //合并u, v int t1 = getf(u); int t2 = getf(v); if (t1 != t2) { //u, v不在同一个集合里 f[t2].p = t1; //将v合并到u的集合中,即将u的根节点作为v的根节点 f[t1].w += f[t2].w; //顺便把威望也加到u的集合的根节点中,对应下面扫根节点找最大威望 } } int main() { int n, m; fbb(); while (~scanf("%d%d", &n, &m)) { for (int i = 1; i <= n; i++) { f[i].p = i; //刚开始没有合并的时候父节点是自己 f[i].w = 0; int t; scanf("%d", &t); for (int j = 1; j <= maxn; j++) { if (t == a[j]) { f[i].w = 1; //是斐波那契数威望值加一 break; } } } for (int i = 1; i <= m; i++) { int u, v; scanf("%d%d", &u, &v); Merge(u, v); //并查集合并u,v } int maxn = numeric_limits<int>::min(); for (int i = 1; i <= n; i++) { if (getf(i) == i) { //比较同一集合中根节点的威望,得到最大威望值maxn maxn = max(maxn, f[i].w); } } printf("%d\n", maxn); } return 0; }