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));
}
}

浙公网安备 33010602011771号