qoj #368. Natural Park

qoj #368. Natural Park

典型的 Subtask 启发解法的题目。

考虑我们知道链的端点为 \((0,n-1)\),此时需要确定整条链。

我们通过二分求出链 \((0,n-1)\) 上的一个点,向两边递归子问题即可。

这里我们考虑二分出链上的最小值,例如我们加入 \(0\)\(x\),判断 \((u,v)\) 是否连通。

初始时我们确定了连通块 \(\{0\}\),接下来要不断确定新的链。

考虑要确定另一个端点为 \(x\) 的链,此时我们需要确定在连通块中的端点。

将其他点设为可用,二分求出端点即可,接下来同链的部分分。

按照树的方法做的话,我们只能求出其一棵生成树。

考虑目前我们在点 \(y\),其存在一条到 \(S\) 中的点 \(x\) 的链,我们按照 \(x \to y\) 的顺序向 \(S\) 中加入链上的点,加入一个点 \(u\) 时确定其到目前 \(S\) 中的其他边。

去掉 \(u\)\(S\) 中的父亲,\(S\) 最多会裂成 \(7\) 块,递归处理即可。

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include "park.h"
using namespace std;
void Answer(int A,int B);
int Ask(int A,int B,int Place[]);
int out_N,ask_Place[1400];
bool help_query_single(vector<int> S,int s,int t){
	for(int i=0;i<out_N;i++){
		ask_Place[i]=0;
	}
	for(int i=0;i<S.size();i++){
		int s_pos=S[i];
		ask_Place[s_pos]=1;
	}
	ask_Place[s]=1;
	ask_Place[t]=1;
	return Ask(min(s,t),max(s,t),ask_Place);
}
bool help_query(vector<int> S,vector<int> T,int s,int t){
	for(int i=0;i<out_N;i++){
		ask_Place[i]=0;
	}
	for(int i=0;i<S.size();i++){
		int s_pos=S[i];
		ask_Place[s_pos]=1;
	}
	for(int i=0;i<T.size();i++){
		int t_pos=T[i];
		ask_Place[t_pos]=1;
	}
	ask_Place[s]=1;
	ask_Place[t]=1;
	return Ask(min(s,t),max(s,t),ask_Place);
}
bool help_connect(int s,int t){
	for(int i=0;i<out_N;i++){
		ask_Place[i]=0;
	}
	ask_Place[s]=1;
	ask_Place[t]=1;
	return Ask(min(s,t),max(s,t),ask_Place);
}
bool tmp_vis[1400];
vector<int> help_chain(int s,int t,vector<int> may){
	vector<int> ans_vec;
	if(!help_connect(s,t)){
		int l=0,r=may.size();
		while(l<r){
			int mid=(l+r)>>1;
			vector<int> tmp;
			for(int i=0;i<=mid;i++){
				tmp.push_back(may[i]);
			}
			if(help_query_single(tmp,s,t)){
				r=mid;
			}
			else{
				l=mid+1; 
			}
		}
		int mid=may[l];
		vector<int> total;
		for(int i=0;i<may.size();i++){
			if(i!=l){
				total.push_back(may[i]);
			}
		}
		vector<int> l_total=help_chain(s,mid,total);
		for(int i=0;i<out_N;i++){
			tmp_vis[i]=false;
		}
		for(int i=0;i<total.size();i++){
			tmp_vis[total[i]]=true;
		}
		for(int i=0;i<l_total.size();i++){
			tmp_vis[l_total[i]]=false;
		}
		vector<int> r_tmp;
		for(int i=0;i<out_N;i++){
			if(tmp_vis[i]){
				r_tmp.push_back(i);
			}
		}
		vector<int> r_total=help_chain(mid,t,r_tmp);
		for(int i=1;i<r_total.size();i++){
			l_total.push_back(r_total[i]);
		}
		ans_vec=l_total;
	}
	else{
		ans_vec.push_back(s);
		ans_vec.push_back(t);
	}
	return ans_vec;
}
struct Edge{
	int u,v;
}edge[1510];
int tot_edge;
bool in_S[1400];
int dfn[1400],dfn_tot[1400];
vector<int> G[1400],help_tmp;
bool vis_dfn[1400],in_S_dfn[1400];
void dfs(int u){
	vis_dfn[u]=true;
	help_tmp.push_back(u);
	for(int i=0;i<G[u].size();i++){
		int v=G[u][i];
		if(!vis_dfn[v]){
			dfs(v);
		}
	}
}
vector<int> help_tree_dfn(vector<int> S){
	for(int i=0;i<out_N;i++){
		vis_dfn[i]=false;
		G[i].clear();
		G[i].shrink_to_fit();
		in_S_dfn[i]=false;
	}
	for(int i=0;i<S.size();i++){
		in_S_dfn[S[i]]=true;
	}
	for(int i=1;i<=tot_edge;i++){
		if(in_S_dfn[edge[i].u]  &&  in_S_dfn[edge[i].v]){
			G[edge[i].u].push_back(edge[i].v);
			G[edge[i].v].push_back(edge[i].u);
		}
	}
	help_tmp.clear();
	help_tmp.shrink_to_fit();
	dfs(S[0]);
	return help_tmp;
}
bool vis_g[1400],vist[1400];
vector<int> g[1400],vec_tmp;
void Dfs(int u){
	vist[u]=true;
	vec_tmp.push_back(u);
	for(int i=0;i<g[u].size();i++){
		int v=g[u][i];
		if(!vist[v]){
			Dfs(v);
		}
	}
}
void add(vector<int> S,int pos){
	if(!help_query_single(S,S[0],pos)){
		return ;
	}
	vector<int> s_sort=help_tree_dfn(S);
	int l=0,r=s_sort.size();
	while(l<r){
		int mid=(l+r)>>1;
		vector<int> tmp;
		for(int i=0;i<=mid;i++){
			tmp.push_back(s_sort[i]);
		}
		if(help_query_single(tmp,tmp[0],pos)){
			r=mid;
		}
		else{
			l=mid+1;
		}
	}
	int s_pos=s_sort[l];
	edge[++tot_edge]=(Edge){s_pos,pos};
	for(int i=0;i<out_N;i++){
		vist[i]=false;
		vis_g[i]=false;
		g[i].clear();
		g[i].shrink_to_fit();
	} 
	for(int i=0;i<s_sort.size();i++){
		if(i!=l){
			vis_g[s_sort[i]]=true;
		}
	}
	for(int i=1;i<=tot_edge;i++){
		if(vis_g[edge[i].u]  &&  vis_g[edge[i].v]){
			g[edge[i].u].push_back(edge[i].v);
			g[edge[i].v].push_back(edge[i].u);
		}
	}
	vector<vector<int>> tmp;
	for(int i=0;i<s_sort.size();i++){
		if(i!=l){
			int pos=s_sort[i];
			if(!vist[pos]){
				vec_tmp.clear();
				vec_tmp.shrink_to_fit();
				Dfs(pos);
				tmp.push_back(vec_tmp);
			}
		}
	}
	for(int i=0;i<tmp.size();i++){
		add(tmp[i],pos);
	}
}
void Detect(int T,int N){
	out_N=N;
	vector<int> S;
	S.push_back(0);
	while(S.size()<N){
		for(int i=0;i<N;i++){
			in_S[i]=false;
		}
		for(int i=0;i<S.size();i++){
			in_S[S[i]]=true;
		}
		int t_pos=-1;
		vector<int> t_list;
		for(int i=0;i<N;i++){
			if(!in_S[i]){
				if(t_pos!=-1){
					t_list.push_back(t_pos);
				}
				t_pos=i;
			}
		}
		vector<int> s_sort=help_tree_dfn(S);
		int l=0,r=s_sort.size();
		while(l<r){
			int mid=(l+r)>>1;
			vector<int> tmp;
			for(int i=0;i<=mid;i++){
				tmp.push_back(s_sort[i]);
			}
			if(help_query(tmp,t_list,tmp[0],t_pos)){
				r=mid;
			}
			else{
				l=mid+1;
			}
		}
		sort(t_list.begin(),t_list.end());
		int s_pos=s_sort[l];
		vector<int> chain_list=help_chain(s_pos,t_pos,t_list);
		for(int i=1;i<chain_list.size();i++){
			int pos=chain_list[i];
			add(S,pos);
			S.push_back(pos);
		}
	}
	for(int i=1;i<=tot_edge;i++){
		Answer(min(edge[i].u,edge[i].v),max(edge[i].u,edge[i].v));
	}
}
posted @ 2026-07-17 20:00  Oken喵~  阅读(3)  评论(0)    收藏  举报