列表

详情


NC50515. 骑士

描述

Z国的骑士团是一个很有势力的组织,帮会中聚集了来自各地的精英。他们劫富济贫,惩恶扬善,受到了社会各界的赞扬。
可是,最近发生了一件很可怕的事情:邪恶的Y国发起了一场针对Z国的侵略战争。战火绵延五百里,在和平环境中安逸了数百年的Z国又怎能抵挡得住Y国的军队。于是人们把所有希望都寄托在了骑士团身上,就像期待有一个真龙天子的降生,带领正义打败邪恶。
骑士团是肯定具备打败邪恶势力的能力的,但是骑士们互相之间往往有一些矛盾。每个骑士有且仅有一个他自己最厌恶的骑士(当然不是他自己),他是绝对不会与最厌恶的人一同出征的。
战火绵延,人们生灵涂炭,组织起一个骑士军团加入战斗刻不容缓!国王交给你了一个艰巨的任务:从所有骑士中选出一个骑士军团,使得军内没有矛盾的两人,即不存在一个骑士与他最痛恨的人一同被选入骑士团的情况,并且使这支骑士军团最富有战斗力。
为描述战斗力,我们将骑士按照1至N编号,给每位骑士估计一个战斗力,一个军团的战斗力为所有骑士的战斗力之和。

输入描述

输入第一行包含一个正整数N,描述骑士团的人数;
接下来N行每行两个正整数,按顺序描述每一名骑士的战斗力和他最痛恨的骑士。

输出描述

输出包含一行,一个整数,表示你所选出的骑士军团的战斗力。

示例1

输入:

3
10 2
20 3
30 1

输出:

30

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 686ms, 内存消耗: 57096K, 提交时间: 2022-06-16 13:54:55

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1000100;
struct node{
	int nt,to;
}a[N];
int h[N],fa[N];
int s[N],n,tot,ans,f[N][2];
bool v[N],vis[N];
void add(int x,int y)
{
	a[++tot].nt=h[x];
	a[tot].to=y;
	h[x]=tot;
	fa[y]=x;
}
void dfs(int x)
{
	v[x]=1;
	f[x][1]=s[x];
	for(int i=h[x];i;i=a[i].nt)
    {
		if(v[a[i].to]==0)
		{
			dfs(a[i].to);
			f[x][0]+=max(f[a[i].to][1],f[a[i].to][0]);
			f[x][1]+=f[a[i].to][0];
		}
	}
}
void dp(int x)
{
	int root=0;
	for(root=x; vis[root]==0; root=fa[root])
    {
		vis[root]=1;
	}
	dfs(root);
    x=fa[root];
	f[x][1]=f[x][0];
	for(x=fa[x];x!=root;x=fa[x])
	{
		f[x][1]=s[x];
		f[x][0]=0;
		for(int j=h[x];j;j=a[j].nt)
		{
			f[x][1]+=f[a[j].to][0];
			f[x][0]+=max(f[a[j].to][1],f[a[j].to][0]);
		}
	}
	f[root][1]=s[root];
	for(int i=h[x];i;i=a[i].nt)
	{
		f[root][1]+=f[a[i].to][0];
	}
	ans+=max(f[root][1],f[root][0]);
}
signed main()
{
    cin>>n;
	for(int i=1; i<=n; i++)
    {
        int u;
        cin>>s[i]>>u;
		add(u,i);
	}
	for(int i=1;i<=n;i++)
	if(v[i]==0)dp(i);
	cout<<ans<<endl;
    return 0;
}

上一题