所有的边是无向的!
想一想也知道,只要有一个人讨厌另外一个人,这两个人最后是不会在一起的。
n个人n条边(图不保证联通),这就是一个环加外向树森林
不能同时取一条边上的两个人,用DP来实现
DFS找环,拆环x,y,分别讨论x不取和y不取
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#define N 2000050
using namespace std;
typedef long long LL;
vector<int> e[N],rec[N];
LL F[N][3],ans1,ans2,ans,V[N];
int fa[N],x,y,n;
bool vis[N],fx[N];
int DFS(int u) {
vis[u] = true;
for (int i=0;i<e[u].size();i++) {
int v = e[u][i];
if (v == -1) continue;
if (v == fa[u]) continue;
if (vis[v]) {
x = u , y = v;
e[u][i] = -1;
int rc = rec[u][i];
e[v][rc] = -1;
} else {
fa[v] = u;
DFS(v);
}
}
return 0;
}
void treeDP(int u) {
vis[u] = true;
fx[u] = true;
for (int i=0;i<e[u].size();i++) {
int v = e[u][i];
if (v == -1) continue;
if (!vis[v]) {
treeDP(v);
F[u][0] += max(F[v][0],F[v][1]);
F[u][1] += F[v][0];
}
}
F[u][1] += V[u];
}
int main()
{
//freopen("knight.in","r",stdin);
//freopen("knight.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++) {
scanf("%lld%d",&V[i],&x);
e[i].push_back(x);
rec[i].push_back( (int)e[x].size() );
e[x].push_back(i);
rec[x].push_back( (int)e[i].size() - 1 );
}
for (int d=1;d<=n;d++) if (!fx[d]) {
//memset(fa,0,sizeof(fa)),x = y = 0;
//memset(vis,0,sizeof(vis));
DFS(d);
ans1 = ans2 = 0LL;
memset(F,0,sizeof(F));
memset(vis,0,sizeof(vis));
treeDP(x);
ans1 = F[x][0];
memset(F,0,sizeof(F));
memset(vis,0,sizeof(vis));
treeDP(y);
ans2 = F[y][0];
LL tmp = max(ans1,ans2);
ans += tmp;
}
printf("%lld\n",ans);
//fclose(stdin);fclose(stdout);
return 0;
}