题目描述
你要组织一个由你公司的人参加的聚会。你希望聚会非常愉快,尽可能多地找些有趣的热闹。但是劝你不要同时邀请某个人和他的上司,因为这可能带来争吵。给定N个人(姓名,他幽默的系数,以及他上司的名字),编程找到能使幽默系数和最大的若干个人。
输入格式
第一行一个整数N(N<100)。接下来有N行,每一行描述一个人的信息,信息之间用空格隔开。姓名是长度不超过20的字符串,幽默系数是在0到100之间的整数。
输出格式
所邀请的人最大的幽默系数和。
样例数据
样例输入
5
BART 1 HOMER
HOMER 2 MONTGOMERY
MONTGOMERY 1 NOBODY
LISA 3 HOMER
SMITHERS 4 MONTGOMERY
样例输出
8
说明
洛谷第四组数据有错,其中有重名情况,WA的不用理他。
题目分析
类似[Ural 1039] 没有上司的晚会
用map处理人的名字,Trie树也可以
源代码
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
inline const long long Get_Int() {
long long num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}
map<string,long long>M;
struct Edge {
int to,next;
} Edge[50005];
string Name[50005],Father[50005];
long long n,cnt=0,Head[50005],f[50005][5],vst[50005],Joy[50005],root;
void AddEdge(long long x,long long y) {
cnt++;
Edge[cnt].to=y;
Edge[cnt].next=Head[x];
Head[x]=cnt;
}
void TreeDp(long long root) {
f[root][0]=0;
f[root][1]=Joy[root];
for(int i=Head[root]; i; i=Edge[i].next) {
int Next=Edge[i].to;
TreeDp(Next);
f[root][0]=max(f[root][0],max(f[root][0]+f[Next][1],f[root][0]+f[Next][0]));
f[root][1]=max(f[root][1],f[Next][0]+f[root][1]);
}
}
int main() {
ios::sync_with_stdio(false);
cin>>n;
for(int i=1; i<=n; i++) {
cin>>Name[i]>>Joy[i]>>Father[i];
M[Name[i]]=i;
}
for(int i=1; i<=n; i++) {
if(Father[i]=="NOBODY")continue;
AddEdge(M[Father[i]],M[Name[i]]);
vst[M[Name[i]]]=1;
}
for(int i=1; i<=n; i++)if(!vst[i])root=i;
TreeDp(root);
printf("%lld\n",max(f[root][0],f[root][1]));
return 0;
}