网友小 Z 的树

网友小 Z 的树

对于 \(n=1\),直接返回 \((1,1)\) 即可。

对于 \(n=2\),直接返回 \((1,2)\) 即可。

对于 \(n=3\),图必为一条链,询问链的形态即可使用两次 \(2\) 操作解决。

对于 \(n=4\),询问任意三点之间答案,若为 \(\{4,4,4,6\}\) 返回 \(6\) 对应的任意两个点,若为 \(\{4,4,6,6\}\) 则返回两个 \(6\) 的公共点。

接下来我们声称能够在得出 \(n=m\) 的直径时,得出 \(n=m+3\) 时的直径。

注意到对于点集 \(S_1 + S_2\) 的直径,必然在 \(S_1\) 和 \(S_2\) 的直径端点中产生。

同时注意到 \(\dbinom{5}{2} = \dbinom{5}{3}\),我们声称每次问出原先的两个直径端点和新加的三个点之间两两距离,就可以求出两两距离,可以在 \(9\) 次内加入 \(3\) 个点。

//Ad astra per aspera
#include "diameter.h"
#include<iostream>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
double num[20][20],ans[20];
int to_id[20][20],id[20];
pair<int,int> find_diameter(int task_id,int n){
	to_id[1][2]=1;
	to_id[1][3]=2;
	to_id[1][4]=3;
	to_id[1][5]=4;
	to_id[2][3]=5;
	to_id[2][4]=6;
	to_id[2][5]=7;
	to_id[3][4]=8;
	to_id[3][5]=9;
	to_id[4][5]=10;
	if(n==1){
		return make_pair(1,1);
	}
	int tot,dot_1,dot_2,len=0;
	if(n==3){
		tot=3;
		if(in(1,2,3)){
			dot_1=2;
			dot_2=3;
			len=2;
		}
		else if(in(2,1,3)){
			dot_1=1;
			dot_2=3;
			len=2;
		}
		else{
			dot_1=1;
			dot_2=2;
			len=2;
		}
		return make_pair(dot_1,dot_2);
	}
	if(n==4){
		tot=4;
		int ask1=query(1,2,3),ask2=query(1,2,4),ask3=query(1,3,4),ask4=query(2,3,4);
		if(ask1+ask2+ask3+ask4==18){
			if(ask1==6){
				dot_1=1;
				dot_2=2;
				len=2;
			}
			else if(ask4==6){
				dot_1=3;
				dot_2=4;
				len=2;
			}
			else{
				dot_1=1;
				dot_2=4;
				len=2;
			}
		}
		else{
			if(ask1==6  &&  ask2==6){
				dot_1=1;
				dot_2=2;
				len=3;
			}
			if(ask1==6  &&  ask3==6){
				dot_1=1;
				dot_2=3;
				len=3;
			}
			if(ask1==6  &&  ask4==6){
				dot_1=2;
				dot_2=3;
				len=3;
			}
			if(ask2==6  &&  ask3==6){
				dot_1=1;
				dot_2=4;
				len=3;
			}
			if(ask2==6  &&  ask4==6){
				dot_1=2;
				dot_2=4;
				len=3;
			}
			if(ask3==6  &&  ask4==6){
				dot_1=3;
				dot_2=4;
				len=3;
			}
		}
		return make_pair(dot_1,dot_2);
	}
	if(n==2){
		tot=2;
		dot_1=1;
		dot_2=2;
		len=1;
		return make_pair(dot_1,dot_2);
	}
	tot=5;
	id[1]=1;
	id[2]=2;
	id[3]=3;
	id[4]=4;
	id[5]=5;
	memset(num,0,sizeof(num));
	memset(ans,0,sizeof(ans));
	int N=0;
	for(int a=1;a<=5;a++){
		for(int b=a+1;b<=5;b++){
			for(int c=b+1;c<=5;c++){
				N++;
				num[N][to_id[a][b]]=1;
				num[N][to_id[a][c]]=1;
				num[N][to_id[b][c]]=1;
				ans[N]=query(id[a],id[b],id[c]);
			}
		}
	}
	for(int i=1;i<=N;i++){
		int idt;
		for(int j=i;j<=N;j++){
			if(num[j][i]!=0){
				idt=j;
				break;
			}
		}
		for(int j=1;j<=N;j++){
			swap(num[i][j],num[idt][j]);
		}
		swap(ans[i],ans[idt]);
		double ttt=num[i][i];
		for(int j=1;j<=N;j++){
			num[i][j]/=ttt;
		}
		ans[i]/=ttt;
		for(int j=i+1;j<=N;j++){
			double tmp=num[j][i];
			for(int k=1;k<=N;k++){
				num[j][k]-=num[i][k]*tmp;
			}
			ans[j]-=ans[i]*tmp;
		}
	}
	for(int i=N;i>=1;i--){
		for(int j=i-1;j>=1;j--){
			double ttt=num[j][i];
			num[j][i]-=ttt*num[i][i];
			ans[j]-=ttt*ans[i];
		}
	}
	for(int a=1;a<=5;a++){
		for(int b=a+1;b<=5;b++){
			int lent=round(ans[to_id[a][b]]);
			if(lent>len){
				dot_1=id[a];
				dot_2=id[b];
				len=lent;
			}
		}
	} 
	while(tot<n){
		id[1]=dot_1;
		id[2]=dot_2;
		int pre=1;
		tot++;
		if(tot>n){
			while(pre==dot_1  ||  pre==dot_2){
				pre++;
			}
			id[3]=pre;
			pre++;
		}
		else{
			id[3]=tot;
		}
		tot++;
		if(tot>n){
			while(pre==dot_1  ||  pre==dot_2){
				pre++;
			}
			id[4]=pre;
			pre++;
		}
		else{
			id[4]=tot;
		}
		tot++;
		if(tot>n){
			while(pre==dot_1  ||  pre==dot_2){
				pre++;
			}
			id[5]=pre;
			pre++;
		}
		else{
			id[5]=tot;
		}
		memset(num,0,sizeof(num));
		memset(ans,0,sizeof(ans));
		N=0;
		for(int a=1;a<=5;a++){
			for(int b=a+1;b<=5;b++){
				for(int c=b+1;c<=5;c++){
					if(a==1  &&  b==2  &&  c==3){
						N++;
						num[N][1]=1;
						ans[N]=len;
					}
					else{
						N++;
						num[N][to_id[a][b]]=1;
						num[N][to_id[a][c]]=1;
						num[N][to_id[b][c]]=1;
						ans[N]=query(id[a],id[b],id[c]);
					}
				}
			}
		}
		for(int i=1;i<=N;i++){
			int idt;
			for(int j=i;j<=N;j++){
				if(num[j][i]!=0){
					idt=j;
					break;
				}
			}
			for(int j=1;j<=N;j++){
				swap(num[i][j],num[idt][j]);
			}
			swap(ans[i],ans[idt]);
			double ttt=num[i][i];
			for(int j=1;j<=N;j++){
				num[i][j]/=ttt;
			}
			ans[i]/=ttt;
			for(int j=i+1;j<=N;j++){
				double tmp=num[j][i];
				for(int k=1;k<=N;k++){
					num[j][k]-=num[i][k]*tmp;
				}
				ans[j]-=ans[i]*tmp;
			}
		}
		for(int i=N;i>=1;i--){
			for(int j=i-1;j>=1;j--){
				double ttt=num[j][i];
				num[j][i]-=ttt*num[i][i];
				ans[j]-=ttt*ans[i];
			}
		}
		for(int a=1;a<=5;a++){
			for(int b=a+1;b<=5;b++){
				int lent=round(ans[to_id[a][b]]);
				if(lent>len){
					dot_1=id[a];
					dot_2=id[b];
					len=lent;
				}
			}
		} 
	}
	return make_pair(dot_1,dot_2);
}
posted @ 2026-08-04 11:36  Oken喵~  阅读(20)  评论(0)    收藏  举报