不明原因50分 求助
查看原帖
不明原因50分 求助
300137
风软一江水、楼主2021/2/8 18:42

思路就是每次找环断开,在当前连通块里分别以两个断点做dp

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const int N = 1000010;

int n,r1,r2,de;
int val[N];
int cnt,head[N],nxt[N * 2],to[N * 2];
long long ans,f[N][2];
bool vis[N];

void add(int u,int v) {
	cnt ++;
	to[cnt] = v;
	nxt[cnt] = head[u];
	head[u] = cnt;
}

void circle(int x,int fa) {
	vis[x] = 1;
	for(int i=head[x] ; i ; i=nxt[i]) {
		int v = to[i];
		if(v == fa) continue;
		if(vis[v]) {
			r1 = x,r2 = v;
			continue;
		}
		circle(v,x);
	}
}

void dfs(int x,int fa) {
	f[x][0] = 0;
	f[x][1] = val[x];
	for(int i=head[x] ; i ; i=nxt[i]) {
		int v = to[i];
		if(v == fa) continue;
		if((x == r1 && v == r2) || (x == r2 && v == r1)) continue;
		dfs(v,x);
		f[x][1] += f[v][0];
		f[x][0] += max(f[v][1],f[v][0]);
	}
}

int main(){
	scanf("%d",&n);
	for(int i=1 ; i<=n ; i++) {
		scanf("%d",&val[i]);
		int v;
		scanf("%d",&v);
		add(v,i);
		add(i,v);
	}
	for(int i=1 ; i<=n ; i++) {
		if(vis[i]) continue;
		r1 = 0,r2 = 0;
		circle(i,0);
		long long tmp = 0;
		dfs(r1,0);
		tmp = f[r1][0];
		dfs(r2,0);
		ans += max(tmp,f[r2][0]);
	}
	printf("%lld",ans);
}
2021/2/8 18:42
加载中...