骑士

https://loj.ac/problem/10162

题目描述

  每个骑士都有一个战斗力和一个厌恶的人,他不会和厌恶的人一起出征,求最多能达到的最大战斗力。

思路

  由于题目中每个点必定会连出一条边,所以对于每个连通块内,必定是一棵基环树,对于基环树,我们很难进行(dp),一个简单的方法是我们先求出那个简单环,随后断开环上的任意一条边,以这条边连接的两个点为根做一次树形(dp),并保证根节点不选即可。

  对于在基环树上找环,我们可以考虑用(dfs)序做,当我们访问到一条边从(dfs)序小的访问到已确定(dfs)序大的节点时,这两个点必定是环上的两点,不断往回跳记录答案即可。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+10;

ll read()
{
	ll res=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){res=(res<<3)+(res<<1)+(ch^48);ch=getchar();}
	return res*w;
}
void write(ll x)
{
	if(x<0){putchar('-');x=-x;}
	if(x>9)write(x/10);
	putchar(x%10+'0');
}

int head[N],tot=1,to[N<<1],nxt[N<<1];
void add_edge(int x,int y)
{
	nxt[++tot]=head[x];
	head[x]=tot;
	to[tot]=y;
}
int dfn[N],idx,fa[N],loop[N],cnt;
void get_loop(int u)
{
	dfn[u]=++idx;
	for(int i=head[u];i;i=nxt[i])
	{
		int v=to[i];
		if(v==fa[u])continue ;
		if(dfn[v])
		{
			if(dfn[v]<dfn[u])continue ;
			loop[++cnt]=v;
			for(;v!=u;v=fa[v])
				loop[++cnt]=fa[v];
		}
		else
		{
			fa[v]=u;
			get_loop(v);
		}
	}
}
ll a[N],f[N][2],st;
void dfs(int u,int fa)
{
//	cout<<u<<':'<<endl;
	f[u][1]=a[u];
	for(int i=head[u];i;i=nxt[i])
	{
		int v=to[i];
		if(v==fa||i==(st^1)||i==st)continue ;
//		cout<<i<<' '<<v<<endl;
		dfs(v,u);
		f[u][0]+=max(f[v][0],f[v][1]);
		f[u][1]+=f[v][0];
	}
}

int main()
{
	int n=read();
	for(int i=1;i<=n;i++)
	{
		a[i]=read();
		int x=read();
		add_edge(i,x);add_edge(x,i);
	}
	ll ans=0;
	for(int i=1;i<=n;i++)
		if(!dfn[i])
		{
			cnt=0;
			get_loop(i);
//			for(int j=1;j<=cnt;j++)
//				cout<<loop[j]<<' ';
//			cout<<endl;
			for(int i=head[loop[1]];i;i=nxt[i])
				if(to[i]==loop[cnt])st=i;
//			cout<<st<<' '<<(st^1)<<endl;
			dfs(loop[1],0);
			ll x=f[loop[1]][0];
			for(int i=head[loop[cnt]];i;i=nxt[i])
				if(to[i]==loop[1])st=i;
			memset(f,0,sizeof(f));
			dfs(loop[cnt],0);
			ans+=max(x,f[loop[cnt]][0]);
//			cout<<x<<' '<<f[loop[cnt]][0]<<endl;
		}
	write(ans);
}
原文地址:https://www.cnblogs.com/fangbozhen/p/11838854.html