Anniversary party
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 9790 Accepted Submission(s): 4186
Problem Description
There is going to be a party to celebrate the 80-th Anniversary of the Ural State University. The University has a hierarchical structure of employees. It means that the supervisor relation forms a tree rooted at the rector V. E. Tretyakov. In order to make the party funny for every one, the rector does not want both an employee and his or her immediate supervisor to be present. The personnel office has evaluated conviviality of each employee, so everyone has some number (rating) attached to him or her. Your task is to make a list of guests with the maximal possible sum of guests' conviviality ratings.
Input
Employees are numbered from 1 to N. A first line of input contains a number N. 1 <= N <= 6 000. Each of the subsequent N lines contains the conviviality rating of the corresponding employee. Conviviality rating is an integer number in a range from -128 to 127. After that go T lines that describe a supervisor relation tree. Each line of the tree specification has the form:
L K
It means that the K-th employee is an immediate supervisor of the L-th employee. Input is ended with the line
0 0
L K
It means that the K-th employee is an immediate supervisor of the L-th employee. Input is ended with the line
0 0
Output
Output should contain the maximal sum of guests' ratings.
Sample Input
7 1 1 1 1 1 1 1 1 3 2 3 6 4 7 4 4 5 3 5 0 0
Sample Output
5
这个的题目和前一篇,POJ2342是一模一样的。但是把POJ的代码往HDU上一交,TLE了。不得不说HDU的数据要比POJ狠一点。
看看POJ的题解:
Click Me(・ω< )★
POJ那个时间宽裕,所以当时用的是双亲表示法,只记录双亲节点。在寻找孩子节点的时候使用了遍历,所以时间复杂度较高。
对于HDU这个题,这样做就超时了。我们最好能用一个方法,既能快速寻找双亲,又能快速寻找孩子。
于是,我在POJ的代码基础上加了一个孩子列表。
嘛,差不多就是个户口本吧。
用一个二维数组,一维是父母节点,另一维是他们的孩子:
0 1 2
1 | 1 2 5
2 | 1 4
3 | 2 6 8
4 | 1 9
5 | 1 7
6 | 1 3
7 | 0
8 | 0
9 | 0
如上图
child[ i ][ 0 ] = n表示 i 的孩子数目是n。
接下来的n个,
child[ i ][ 1 ]……
child[ i ][ n ]是她的孩子们。
这样我们可以很方便的查询他们的孩子节点,而避免因为遍历而超时。
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int par[6066];//双亲节点
int child[6066][6066];//孩子列表(户口本)
bool vis[6066];
int dp[6066][5];
int n;
void init(int n)
{
for(int i=1; i<=n; i++)
{
par[i]=i;
vis[i]=0;
dp[i][1]=0;
dp[i][0]=0;
child[i][0]=0;
}
}
void dfs(int root)
{
vis[root]=1;
for(int i=1; i<=child[root][0]; i++)//查询孩子节点的时候可以直接用户口本,而不用全抓来做亲子鉴定
{
int son=child[root][i];
if(!vis[son])
{
dfs(son);
dp[root][1]+=dp[son][0];
dp[root][0]+=max(dp[son][0],dp[son][1]);
}
}
}
int main()
{
while(~scanf("%d",&n)&&n)
{
init(n);
int a,b;
for(int i=1; i<=n; i++)
{
scanf("%d",&dp[i][1]);
}
while(scanf("%d%d",&a,&b))
{
if(a==0&&b==0)
{
break;
}
par[a]=b;
child[b][0]++;//孩子数目加1
child[b][child[b][0]]=a;//记录孩子
}
int root=1;
for(int i=1;i<=n;i++)
{
if(i==par[i])
{
root=i;
break;
}
}
dfs(root);
printf("%d\n",max(dp[root][1],dp[root][0]));
}
return 0;
}
不过本人感觉这种方法实在逊爆了!这么low,还浪费内存,用这样low的代码AC了就算不能表现出作为一个ACMer的意志。
于是改用了结构体来储存一个节点的父母,孩子,和兄弟节点的指针。
整个关系图是用结构体链表来表示的。
这样可以节省内存,并且结构上看起来更加简洁明了。
struct nodes
{
nodes *parent;
nodes *child;
nodes *borther;
int val[5];
} node[6066];
{
nodes *parent;
nodes *child;
nodes *borther;
int val[5];
} node[6066];
如果一个节点有多个孩子是不容易表示的,我们不可能在一个节点上分配child1,child2……childn那么多指针。天晓得他超生了多少个??
我的孩子的弟弟肯定也是我的孩子。所以我们只需要记录下我的大儿子或者大女儿,然后询问他的兄弟是谁就可以了。
brother
brother
老爸 ————>二叔——————>三姑
parent ↑ ↓ child brother brother brother
我 ————————>二妹———————————————>三妹————>我没有弟弟妹妹了(NULL)
parent ↑ ↓ child ↑ ↓ brother
大儿子——>小女儿——>再给我生个妹妹啦~(NULL) 侄女————>我也想要妹妹……(NULL)
brother brother
PS:虽然很美好,但以上纯属YY……
那么在本题中,老爸自然是直接上司,我的弟弟妹妹自然是同一个上司直接领导下的同事,儿女自然是直接下属
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct nodes
{
nodes *parent;
nodes *child;
nodes *borther;
int val[5];
} node[6066];
void dfs(nodes* root)
{
nodes* p=root;
if(p->child!=NULL)
{
p=p->child;
dfs(p);
root->val[1]+=p->val[0];
root->val[0]+=max(p->val[0],p->val[1]);
while(p->borther!=NULL)
{
p=p->borther;
dfs(p);
root->val[1]+=p->val[0];
root->val[0]+=max(p->val[0],p->val[1]);
}
}
}
int main()
{
int n;
while(~scanf("%d",&n)&&n)
{
int a,b;
for(int i=1; i<=n; i++)
{
scanf("%d",&node[i].val[1]);
node[i].borther=NULL;
node[i].child=NULL;
node[i].parent=NULL;
node[i].val[0]=0;
}
while(scanf("%d%d",&a,&b))
{
if(a==0&&b==0)
{
break;
}
node[a].parent=&node[b];
nodes *p=&node[b];
if(p->child!=NULL)
{
p=p->child;
while(p->borther!=NULL)
{
p=p->borther;
}
p->borther=&node[a];
}
else
{
p->child=&node[a];
}
}
nodes* root=&node[1];
while(root->parent!=NULL)
{
root=root->parent;
}
dfs(root);
printf("%d\n",max(root->val[1],root->val[0]));
}
return 0;
}
左:大女儿
右:小女儿
反正没人会看见,我就YY一下~23333