来来来!!!
看题了!!!
Z 国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英。他们劫富济贫,惩恶扬善,受到社会各界的赞扬。
最近发生了一件可怕的事情,邪恶的 Y 国发动了一场针对 Z 国的侵略战争。战火绵延五百里,在和平环境中安逸了数百年的 Z 国又怎能抵挡的住 Y 国的军队。于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一个真龙天子的降生,带领正义打败邪恶。
骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一些矛盾。每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己),他是绝对不会与自己最厌恶的人一同出征的。
战火绵延,人民生灵涂炭,组织起一个骑士军团加入战斗刻不容缓!国王交给了你一个艰巨的任务,从所有的骑士中选出一个骑士军团,使得军团内没有矛盾的两人(不存在一个骑士与他最痛恨的人一同被选入骑士军团的情况),并且,使得这支骑士军团最具有战斗力。
为了描述战斗力,我们将骑士按照 11 至 nn 编号,给每名骑士一个战斗力的估计,一个军团的战斗力为所有骑士的战斗力总和。
输入格式
第一行包含一个整数 nn,描述骑士团的人数。
接下来 nn 行,每行两个整数,按顺序描述每一名骑士的战斗力和他最痛恨的骑士。
输出格式
应输出一行,包含一个整数,表示你所选出的骑士军团的战斗力。
输入输出样例
3 10 2 20 3 30 1
30
说明/提示
数据规模与约定
对于 30\%30% 的测试数据,满足 n \le 10n≤10;
对于 60\%60% 的测试数据,满足 n \le 100n≤100;
对于 80\%80% 的测试数据,满足 n \le 10 ^4n≤104。
对于 100\%100% 的测试数据,满足 1\le n \le 10^61≤n≤106,每名骑士的战斗力都是不大于 10^6106 的正整数。
——————————————————————————————————————————————————————————————————————
想到了神马
来,在看一道简单题。
来来来!!!
看题了!!!
P1352 没有上司的舞会
标签
相关讨论
推荐题目
题目描述
某大学有 nn 个职员,编号为 1\ldots n1…n。
他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。
现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数 r_iri,但是呢,如果某个职员的直接上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。
所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。
输入格式
输入的第一行是一个整数 nn。
第 22 到第 (n + 1)(n+1) 行,每行一个整数,第 (i+1)(i+1) 行的整数表示 ii 号职员的快乐指数 r_iri。
第 (n + 2)(n+2) 到第 (2n + 1)(2n+1) 行,每行输入一对整数 l, kl,k,代表 kk 是 ll 的直接上司。
输出格式
输出一行一个整数代表最大的快乐指数。
输入输出样例
7 1 1 1 1 1 1 1 1 3 2 3 6 4 7 4 4 5 3 5
5
说明/提示
数据规模与约定
对于 100\%100% 的数据,保证 1\leq n \leq 6 \times 10^31≤n≤6×103,-128 \leq r_i\leq 127−128≤ri≤127,1 \leq l, k \leq n1≤l,k≤n,且给出的关系一定是一棵树。
如果大家这道题都不会的话,建议先去做这道题。
OK,那么如果你已经做出了这道题。
那么骑士这道题对你也就没有深莫难度了。
下面是骑士的题解:
————————————————————————————————————————————————————————————————————
树形DP,没有上司的舞会的模型。。。
根据题目可以知道, 每一个联通块里有且只有一个环, 所以我们找到这个环然后从中间把它断开, 对断开的两个端点u1, u2, 分别舞会。
设dp[u][0]为不选u, dp[u][1]为选u,
那么这个联通块答案就是max(dp[u1][0], dp[u2][0])。
注意有好多联通块。对于所有联通块跑dp,加起来就是答案
大家是不是懂了。
下面是伪代码:
//写一下伪代码
//在存的时候存一下每个人最讨厌的人为他的父亲
//对每个没访问的点DFS
//在这个没访问的点所在的连通块上找环
//找到以后强制不选它的父亲对它进行DP
//然后强制不选它对它的父亲进行DP
//然后取一个最大值即可
//在DP里面
//先考虑f[x][0]是不选x,初始值为0
//f[x][1]是选x,初值为val[x]
//这是一个很好的赋值方法
//然后跑DP就行了
然后是正品:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #define maxn 2000000 6 using namespace std; 7 int n,cnt; 8 long long ans; 9 int root; 10 long long f[maxn][2]; 11 int head[maxn],val[maxn],vis[maxn],fa[maxn]; 12 struct edge{ 13 int pre,to; 14 }e[maxn]; 15 int in(){ 16 char a=getchar(); 17 while(a<'0'||a>'9'){ 18 a=getchar(); 19 } 20 int t=0; 21 while(a<='9'&&a>='0'){ 22 t=(t<<1)+(t<<3)+a-'0'; 23 a=getchar(); 24 } 25 return t; 26 } 27 void add(int from,int to){ 28 e[++cnt].pre=head[from]; 29 e[cnt].to=to; 30 head[from]=cnt; 31 } 32 void dp(int now){ 33 vis[now]=1; 34 f[now][0]=0,f[now][1]=val[now]; 35 for(int i=head[now];i;i=e[i].pre){ 36 int go=e[i].to; 37 if(go!=root){ 38 dp(go); 39 f[now][0]+=max(f[go][1],f[go][0]); 40 f[now][1]+=f[go][0]; 41 } 42 else{ 43 f[go][1]=-maxn; 44 } 45 } 46 } 47 void find_circle(int x){ 48 vis[x]=1; 49 root=x; 50 while(!vis[fa[root]]){ 51 root=fa[root]; 52 vis[root]=1; 53 }//找环 54 dp(root); 55 long long t=max(f[root][0],f[root][1]); 56 vis[root]=1; 57 root=fa[root]; 58 dp(root); 59 ans+=max(t,max(f[root][0],f[root][1])); 60 return; 61 } 62 int main(){ 63 //freopen("a.in","r",stdin); 64 n=in(); 65 for(int i=1;i<=n;i++){ 66 val[i]=in(); 67 int x=in(); 68 add(x,i); 69 fa[i]=x; 70 } 71 for(int i=1;i<=n;i++){ 72 if(!vis[i]){ 73 find_circle(i); 74 } 75 } 76 printf("%lld\n",ans); 77 return 0; 78 }
这道题比较考验代码能力。
大家应该独立完成。