1. 程式人生 > >九校聯考-DL24 涼心模擬 Day1T2 烯烴 (olefin)

九校聯考-DL24 涼心模擬 Day1T2 烯烴 (olefin)

題目描述

銀企鵝非常擅長化學。有一天他在試圖命名一個巨大的單烯烴分子的時候,想到了一個問題。

給你一棵樹,一些邊有標記,對於每條有標記的邊,在樹中找到包含這條邊的一條最長鏈,並輸出長度。

輸入輸出格式

輸入格式

第一行一個整數 idid 表示測試點的編號。

多組資料,第二行一個整數 TT 表示資料組數。

對於每組資料,第一行兩個整數 nn, mm 表示節點的個數,和被標記的邊的個數。

我們規定 11 是根,第二行 n1n−1 個整數給出 2n2 \sim n 父親的編號,保證fai<ifa_i<i

第三行 mm 個整數範圍在 [

2,n][2, n] 表示哪個點的父邊被標記過。

輸出格式

對於每組資料輸出一行 mm 個整數,必須與輸入的邊順序一致,給出的是在這條邊必選的情況下樹中最長鏈的長度。

輸入輸出樣例

輸入樣例#1:

0
1
10 3
1 2 3 1 4 6 7 3 8
10 7 9

輸出樣例#1:

8 8 6

資料範圍

測試點	   n ≤	  m ≤	T ≤	     特殊約定
1, 2	 100	n − 1	100	     無
3, 4	 10^5	10	    100	     無
5	     10^5	n − 1	100	   樹是一條鏈
6	     10^5	n − 1	100	   所有 fa_i=1
7, 8, 9,  10	10^5	n − 1	100	無

解題分析

直接DFSDFS預處理出子樹中最深和次深的深度, 再一遍DFSDFS即可。

程式碼如下:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cctype>
#include <ctime>
#include <cmath>
#define R register
#define IN inline
#define File freopen("olefin.in", "r", stdin), freopen("olefin.out", "w", stdout)
#define W while #define MX 100050 inline char nc() { static const int buflen=1e6; static char buf[buflen],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,buflen,stdin),p1==p2)?EOF:*p1++; } #define gc nc() template <class T> IN void in(T &x) { x = 0; R char c = gc; for (; !isdigit(c); c = gc); for (; isdigit(c); c = gc) x = (x << 1) + (x << 3) + c - 48; } int head[MX], ans[MX], dep[MX], fir[MX], sec[MX], sta[MX]; bool mark[MX]; struct Edge {int to, nex;} edge[MX << 1]; int dot, line, cnt; IN void add(R int from, R int to) {edge[++cnt] = {to, head[from]}, head[from] = cnt;} void DFS(R int now) { if(!head[now]) return fir[now] = dep[now], void(); for (R int i = head[now]; i; i = edge[i].nex) { dep[edge[i].to] = dep[now] + 1; DFS(edge[i].to); if(fir[now] < fir[edge[i].to]) sec[now] = fir[now], fir[now] = fir[edge[i].to]; else if(sec[now] < fir[edge[i].to]) sec[now] = fir[edge[i].to]; } } void calc(R int now, R int mx) { for (R int i = head[now]; i; i = edge[i].nex) { R int del = mx; if(fir[edge[i].to] == fir[now]) del = std::max(sec[now] - dep[now], mx); else del = std::max(fir[now] - dep[now], mx); if(mark[edge[i].to]) ans[edge[i].to] = del + fir[edge[i].to] - dep[now]; calc(edge[i].to, del + 1); } } void out(R int now) { if(!now) return; out(now / 10); putchar('0' + now % 10); } int main(void) { int T, buf; in(dot); in(T); W (T--) { in(dot), in(line); std::memset(head, cnt = 0, sizeof(head)); std::memset(fir, 0, sizeof(fir)); std::memset(sec, 0, sizeof(sec)); std::memset(mark, false, sizeof(mark)); dep[1] = 0; for (R int i = 2; i <= dot; ++i) in(buf), add(buf, i); for (R int i = 1; i <= line; ++i) in(buf), mark[buf] = true, sta[i] = buf; DFS(1); calc(1, 0); for (R int i = 1; i <= line; ++i) out(ans[sta[i]]), putchar(' '); if(line) puts(""); } }