zoj 3516は木と関連しています
2045 ワード
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4381
Conttest:ZOJ Monthly、July 2011
一本の木をあげます.10000個のノードで、各ノードには一つの権利があります.各ノードの権利値と父ノードを教えてください.その後、10000個のクエリをして、各ノードをルートとする子樹の最大3つの値を調べてください.もし3個の出力-1.
息子のノードを預けたくないので、各ノードの父ノードを預けて、それから毎回すべてのノードをスキャンして、葉っぱのノードを上に送ります.ちょっと注意してください.スキャンが多すぎるのを避けるために、上に送る過程で、あるノードの父ノードも息子ノードがない場合、直接にノードを上に送ります.(最後に非常に特殊なことを発見しました.やはり3*10^7になります.)
一番いい解法はやはりvectorで息子のノードを預けて、dfsを一つだけ預けたらいいです....一本の木に対してDFSはやりたい放題です.
コード:
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<memory.h>
using namespace std;
const int N=10010;
int m, n;
struct node
{
int parent;
int sonnum, cnt, a[3];
void init()
{
sonnum = 0;
cnt = 1;
}
} a[N];
int cmp(int a, int b)
{
return a>b;
}
void fun(int i)
{
int l, k, j = a[i].parent;
int b[6], bn;
bn = 0;
for(k=0; k<a[i].cnt; k++)
b[bn++] = a[i].a[k];
for(k=0; k<a[j].cnt; k++)
b[bn++] = a[j].a[k];
sort(b, b+bn, cmp);
if(bn<=3)
a[j].cnt = bn;
else
a[j].cnt = 3;
for(k=0; k<a[j].cnt; k++)
a[j].a[k] = b[k];
a[j].sonnum--;
}
int main()
{
int i, j, k, cas1=1, flag;
while(scanf("%d", &n)!=EOF)
{
for(i=0; i<n; i++)
a[i].init();
scanf("%d", &a[0].a[0]);
for(i=1; i<n; i++)
{
scanf("%d%d", &a[i].parent, &a[i].a[0]);
j = a[i].parent;
a[j].sonnum++;
}
flag = 1;
while(flag)
{
for(i=1; i<n; i++)
{
j = i;
while(j!=0 && a[j].sonnum==0 && a[j].parent!=-1)
{
flag = 0;
fun(j);
k = j;
j = a[j].parent;
a[k].parent = -1;
}
}
if(flag==0)
flag = 1;
else
break;
}
//printf("Case #%d:
", cas1++);
scanf("%d", &m);
while(m--)
{
scanf("%d", &i);
if(a[i].cnt<3)
printf("-1
");
else
printf("%d %d %d
", a[i].a[0], a[i].a[1], a[i].a[2]);
}
}
return 0;
}