Misha and Grisha are funny boys, so they like to use new underground. The underground has n stations connected with n - 1 routes so that each route connects two stations, and it is possible to reach every station from any other.ios
The boys decided to have fun and came up with a plan. Namely, in some day in the morning Misha will ride the underground from station s to station f by the shortest path, and will draw with aerosol an ugly text "Misha was here" on every station he will pass through (including s and f). After that on the same day at evening Grisha will ride from station t to station f by the shortest path and will count stations with Misha's text. After that at night the underground workers will wash the texts out, because the underground should be clean.ide
The boys have already chosen three stations a, b and c for each of several following days, one of them should be station s on that day, another should be station f, and the remaining should be station t. They became interested how they should choose these stations s, f, t so that the number Grisha will count is as large as possible. They asked you for help.ui
Inputspa
The first line contains two integers n and q (2 ≤ n ≤ 105, 1 ≤ q ≤ 105) — the number of stations and the number of days.rest
The second line contains n - 1 integers p2, p3, ..., pn (1 ≤ pi ≤ n). The integer pimeans that there is a route between stations pi and i. It is guaranteed that it's possible to reach every station from any other.code
The next q lines contains three integers a, b and c each (1 ≤ a, b, c ≤ n) — the ids of stations chosen by boys for some day. Note that some of these ids could be same.blog
Outputthree
Print q lines. In the i-th of these lines print the maximum possible number Grisha can get counting when the stations s, t and f are chosen optimally from the three stations on the i-th day.ip
Examplesci
3 2
1 1
1 2 3
2 3 3
2
3
4 1
1 2 3
1 2 3
2
Note
In the first example on the first day if s = 1, f = 2, t = 3, Misha would go on the route 1 2, and Grisha would go on the route 3 1 2. He would see the text at the stations 1 and 2. On the second day, if s = 3, f = 2, t = 3, both boys would go on the route 3 1 2. Grisha would see the text at 3 stations.
In the second examle if s = 1, f = 3, t = 2, Misha would go on the route 1 2 3, and Grisha would go on the route 2 3 and would see the text at both stations.
題意:給定一個含有N個節點的樹,和Q個羣問,每個詢問包括三個整數,a,b,c 。 讓求出這三個整數構成的兩個路徑中交點個數的最大值。
思路:
首先咱們應該知道這樣的問題,若是這三個整數構成了這樣的兩個路徑,a到b,和,c到b 這兩個路徑。
定義a到b的距離是lab,其餘類推。那麼這兩個路徑的交點個數是 ( lab + lbc - lac ) / 2 + 1
那麼咱們用倍增在線LCA求任意兩個節點的最短路徑的距離,而後枚舉a,b,c分別作爲交點的路徑狀況的最大值便是答案。
細節見代碼:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #include <vector> #include <iomanip> #define ALL(x) (x).begin(), (x).end() #define dll(x) scanf("%I64d",&x) #define xll(x) printf("%I64d\n",x) #define sz(a) int(a.size()) #define all(a) a.begin(), a.end() #define rep(i,x,n) for(int i=x;i<n;i++) #define repd(i,x,n) for(int i=x;i<=n;i++) #define pii pair<int,int> #define pll pair<long long ,long long> #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) #define MS0(X) memset((X), 0, sizeof((X))) #define MSC0(X) memset((X), '\0', sizeof((X))) #define pb push_back #define mp make_pair #define fi first #define se second #define eps 1e-6 #define gg(x) getInt(&x) #define db(x) cout<<"== [ "<<x<<" ] =="<<endl; using namespace std; typedef long long ll; ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} ll lcm(ll a,ll b){return a/gcd(a,b)*b;} ll powmod(ll a,ll b,ll MOD){ll ans=1ll;while(b){if(b&1)ans=ans*a%MOD;a=a*a%MOD;b>>=1;}return ans;} inline void getInt(int* p); const int maxn=1000010; const int inf=0x3f3f3f3f; /*** TEMPLATE CODE * * STARTS HERE ***/ const int N = 1e5+7; std::vector<int> son[N]; int depth[N],fa[N][21],in[N],a,b; // depth[i] -> i 節點的深度 // fa[i][j] -> i 節點向上移動2^j個節點後的祖先 // fa[i][0] -> i 向上移動1個節點後的祖先,即父節點 // in[i] i節點的入度,用來找樹根用的。 // a b 爲讀邊用的。 int n; int m; void buildtree() { for(int i=2;i<=n;i++) { a=i; scanf("%d",&b); son[a].push_back(b); son[b].push_back(a); } } void dfs(int rt,int prev) { depth[rt]=depth[prev]+1; fa[rt][0]=prev; for(int i=1;i<20;i++) { fa[rt][i]=fa[fa[rt][i-1]][i-1]; } for(int i=0;i<son[rt].size();i++) { if(son[rt][i]==prev) continue; dfs(son[rt][i],rt); } } int LCA(int x,int y) { if(depth[x]<depth[y]) swap(x,y); for(int i=19;i>=0;i--) { if(depth[x]-(1<<i)>=depth[y]) { x=fa[x][i]; } } if(x==y) { return x; } for(int i=19;i>=0;i--) { if(fa[x][i]!=fa[y][i]) { x=fa[x][i]; y=fa[y][i]; } } return fa[x][0]; } int dist(int a,int b) { int u=LCA(a,b); int L=depth[a]+depth[b]-2*depth[u]; return L; } int main() { // freopen("C:\\Users\\DH_M\\Desktop\\code_io\\in.txt.txt","r",stdin); // freopen("C:\\Users\\DH_M\\Desktop\\code_io\\out.txt.txt","w",stdout); scanf("%d",&n); scanf("%d",&m); buildtree(); depth[0]=-1; int rt=1;// root dfs(rt,rt); int c; for(int i=1;i<=m;i++) { scanf("%d %d %d",&a,&b,&c); int ans=0; int lab,lbc,lac,l1,l2,l3; lac=dist(a,c); lab=dist(a,b); lbc=dist(b,c); l1=(lab+lbc-lac)/2; l2=(lab+lac-lbc)/2; l3=(lac+lbc-lab)/2; ans=max(l1,max(l2,l3)); printf("%d\n",ans+1); } return 0; } inline void getInt(int* p) {char ch;do {ch = getchar();} while (ch == ' ' || ch == '\n');if (ch == '-') {*p = -(getchar() - '0'); while ((ch = getchar()) >= '0' && ch <= '9') {*p = *p * 10 - ch + '0';}} else {*p = ch - '0';while ((ch = getchar()) >= '0' && ch <= '9') {*p = *p * 10 + ch - '0';}}}