链接
Google Codejam 2016 Round1A Problem C BFFs
题意
n个小朋友要坐成一个圈。每个小朋友心中都有一个Best Friend Forever。要保证每个人的左右至少有一个是他的BFF,问最多能让多少人做成一个圈。
思路
n只有1000,每个点的出度也都是1。看上去就不需要套用某种算法。综合的考虑一下,如果有m个人的BFF关系正好形成一个环,那么他们就可以成为一种结果,并且这个环中不能有别的人插入了。另外一种情况就是一条链,在这条链中有至少两个点A和B的BFF关系是相互的,A侧的人的关系依次指向A,B侧依次指向B,那么这条链也是可以成为结果,并且可以有多条这样的链构成最够的答案。
所以方法就是先求环的最大值,再累加出链的最大值。
代码
#include <bits/stdc++.h>
#define LL long long
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MAXN 1005
using namespace std;
bool vis[MAXN][MAXN], mp[MAXN];
int cnt[MAXN];
int a[MAXN], d[MAXN];
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
int T;
scanf("%d", &T);
int cas = 0;
while (T--){
int n;
scanf("%d", &n);
for (int i = 1; i <= n; ++i){
scanf("%d", &a[i]);
}
memset(cnt, 0, sizeof(cnt));
memset(d, 0, sizeof(d));
int ans = 0;
for (int i = 1; i <= n; ++i){
memset(mp, 0, sizeof(mp));
int x = i;
mp[x] = true;
while (true){
x = a[x];
if (mp[x]) break;
mp[x] = true;
++cnt[i];
}
if (x == i){
ans = max(ans, cnt[i] + 1);
}
}
for (int i = 1; i <= n; ++i){
for (int j = 1; j <= n; ++j){
if (a[a[j]] == j) continue;
d[a[j]] = max(d[a[j]], d[j] + 1);
}
}
int res = 0;
for (int i = 1; i <= n; ++i){
if (a[a[i]] != i) continue;
res += d[i] + d[a[i]] + 2;
}
res >>= 1;
ans = max(ans, res);
printf("Case #%d: %d\n", ++cas, ans);
}
}