Time Limit: 1 second
Memory Limit: 128 MB
【问题描述】
你要组织一个由你公司的人参加的聚会。你希望聚会非常愉快,尽可能多地找些有趣的人。但是劝你不要同时邀请某个人和他的上司,因为这可能带来争吵。给定N个人(姓名,他幽默的系数,以及他上司的名字),找到能使幽默系数和最大的若干个人。
【输入格式】
第一行一个整数N(N<100)。接下来有N行,每一行描述一个人,信息之间用空格隔开。姓名是长度不超过20的字符串。幽默系数是在0到100之间的整数
【输出格式】
邀请的人最大的幽默系数和
Sample Input
15
VSCTPBX 80 NOBODY
XKRQHC 98 VSCTPBX
KJ 92 XKRQHC
IT 86 XKRQHC
CJ 54 XKRQHC
XACEH 8 KJ
QTTMYG 37 KJ
GW 82 KJ
LF 15 CJ
IVUUW 26 CJ
IBCIKUQ 70 CJ
JGHQGBWX 15 XACEH
HBPMO 59 QTTMYG
FXB 59 QTTMYG
OVRVIB 73 GW
Sample Output
575
【题目链接】:http://noi.qz5z.com/viewtask.asp?id=9935
【题解】
先给那n个人打上标记;->用map来打标记
打完之后;
如果有某一个人的上司没有被打上标记;
那么那个人的上司就是所有人的….恩…终极上司;
把那个人标记为n+1;
则整个关系网的根节点就是n+1;
然后就是树形DP了
这里说的上司来了,它就不来的;
指的是某一个人的直系上司;(间接的不算);
这样在f数组的每个域存两个值,一个值为l,一个值为bl;(来和不来拼音的第一个字母)
如果这个人来了,那么
f[i].l = a[i]+∑f[j].bl;
f[i].bl = ∑max(f[j].l,f[j].bl);->因为i不来,所以他的直系下属们就happy了^_^
(这里的j是i的直系儿子);
最后输出max(f[n+1].l,f[n+1].bl);
其实肯定是f[n+1].bl大一点的;
因为n+1来了也没有意义;
那n个人里面都没有他。他的快乐值是0。。
(果然是高处不胜寒吗?若有所思^_^)
【完整代码】
#include <cstdio>
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
#define rei(x) scanf("%d",&x)
#define rep1(i,x,y) for (int i = x;i <= y;i++)
#define pb push_back
const int MAXN = 1e2+10;
struct abc
{
int l,bl;
}f[MAXN];
int n,cnt = 0,root;
int a[MAXN];
map <string,int> dic;
vector <int> G[MAXN];
string name[MAXN],name2[MAXN];
void dfs(int x)
{
int len = G[x].size();
int tbl = 0,tl = a[x];
rep1(i,0,len-1)
{
int y = G[x][i];
dfs(y);
tbl+=max(f[y].l,f[y].bl);
tl+=f[y].bl;
}
f[x].l = tl,f[x].bl = tbl;
}
int main()
{
//freopen("F:\\rush.txt","r",stdin);
rei(n);
rep1(i,1,n)
{
cin >> name[i] >> a[i] >> name2[i];
dic[name[i]] = i;
}
rep1(i,1,n)
{
if (!dic[name2[i]]) dic[name2[i]] = n+1;
int t = dic[name2[i]];
G[t].pb(i);
}
root = n+1;
dfs(root);
printf("%d\n",max(f[root].l,f[root].bl));
return 0;
}