カメレオン愛
JOI Zooには、\(2N \)個のカメレオンがあり、\(1 \ ldots 2N \)と番号が付けられています。その中で、\(N \)カメレオンの性別はXで、他の\(N \)の性別はYです。
各カメレオンは原色を持っています。原色に関する公開情報は次のとおりです。
- 性別Xのすべてのカメレオンの原色は異なります。
- セックスXのカメレオンごとに、同じ原色のユニークなカメレオンがあり、セックスはYです。
今、ジョイ動物園は愛の季節です。各カメレオンは別のカメレオンと恋に落ちました。ラブパートナーに関する公開情報は次のとおりです。
- それぞれのカメレオンは異性の唯一のものに捧げられています。
- カメレオンとそのパートナーの色は異なります。
- 2つのカメレオンが同時に別のカメレオンを追いかけることはありません。
カメレオンの一部を招集して会議を開催できます。ミーティングに参加しているカメレオン\(s \)の場合、\(t \)をその愛のオブジェクトとします。\(s \)の肌の色は以下によって決定されます:
- \(t \)がこの会議に参加した場合、\(s \)の色は\(t \)の元の色です。
- 場合は、\(tは\)この会議に参加しなかった、\(S \)色がある\(S \)原色。
カメレオンの色は、会議ごとに異なる場合があります。主催した会議では、フィールド上のすべてのカメレオンの肌の色のタイプの数を取得できます。
カメレオンも退屈なので、\(20 \、000 \)回の会議しか主催できません。同時に、取得した情報に基づいて、どのカメレオンが同じ原色を持っているかを判別する必要があります。\(20 \、000 \)回を超える会議を
組織しないことを前提に、同じ原色のすべてのカメレオンを判別するプログラムを作成してください。
\(2 \ N \ le 500 \)。
解決策
https://hk-cnyali.com/2020/03/24/"JOISC-2020-Day2 "Chameleon Love-Interaction-Bipartite Diagram /
https://blog.csdn.net/zxyoi_dreamer/article/details/105255333
最初にいくつかのマークを指定します:
-
\(x '\):\(x \)と同じカラーポイント。
-
\(L(x)\):\(x \)好きなポイント。
-
\(L ^ {-1}(x)\):\(x \)のように。
サイズ\(2 \)のすべてのセットの答えを最初に尋ねることを検討してください。答えが\(1 \)または\(2 \)のみである場合があることを見つけるのは難しくありません。
答えは、\(1 \)の 3つのケースです。\(\ {x、x '\}、\ {x、L(x)\}、\ {x、L ^ {-1}(x)\} \ )。後者の2つのタイプは、\(L(x)\ neq L ^ {-1}(x)\)の場合にのみ表示されます。
点のペア\((x、y)\)にエッジに接続された\(1 \)の答えを与えると、各点の次数は\(1 \)または\(3 \)のみになります。
-
ポイントの次数が\(1 \)の場合、同じ色のポイントを直接取得できます。
-
点の次数が\(3 \)の場合、\(x \)に設定し、3つの辺は\((x、x ')、(x、L(x))、(x、L ^ {-1 }(x))\)。ちょうど尋ねる'{X、X \(\ \、L(X)\ {X、X} ^ {、L - 1}(X)\}、\ {X、L(x)は、L ^ { -1}(x)\} \)、これらの3つのセット、答えは\(2,1,2 \)であり、\(L(x)\)と\(L ^ {-1 }(L(x))\)。最後に、処理するだけで同じカラーポイントを取得できます。
このようにして、\(O(n ^ 2)\)を尋ねる方法を得ました。
前半の複雑さを最適化することを検討してください。
これらのエッジによって形成されるグラフが2部グラフであることを見つけるのは難しくありません。\(i \)ポイントと\(1 \ sim i-1 \)ポイントの間の現在の接続エッジが処理されるとすると、\(1 \ sim i- 1 \)これらのポイントは2つの独立したセットに分割され、セット内にエッジがないことを満たします(激しいカラーリングを処理できます)。
独立セットの性質に応じてエッジがあるかどうかを判断できます。セット\(S \)は、\(\ texttt {Query}(S)= | S | \)の場合に限り、独立セットです。つまり、\(\ texttt {Query}(\ {S、i \})\ ne | S | + 1 \)の場合に限り、点\(i \)と独立セット\(S \)にエッジがあります。。
したがって、エッジを2ポイントずつ1つずつ見つけることができます。複雑さ\(O(n \ log n)\)。
CO int N=1e3+10;
vector<int> to[N];
int col[N];
vector<int> node[2];
int L[N],vis[N];
void dfs(int x,int c){
col[x]=c,node[c].push_back(x);
for(int y:to[x])if(col[y]==-1) dfs(y,!c);
}
void calc(vector<int> vec,int x){
while(1){
vec.push_back(x);
if(Query(vec)==(int)vec.size()) return;
vec.pop_back();
int l=0,r=vec.size()-1,goal=-1;
while(l<=r){
int mid=(l+r)>>1;
vector<int> tmp(vec.begin()+l,vec.begin()+mid+1);
tmp.push_back(x);
if(Query(tmp)!=(int)tmp.size()) goal=mid,r=mid-1;
else l=mid+1;
}
if(goal==-1) return;
int y=vec[goal];
to[x].push_back(y),to[y].push_back(x);
vec.erase(vec.begin()+goal);
}
}
void get_edges(int x){
node[0].clear(),node[1].clear();
fill(col,col+x,-1);
for(int i=1;i<x;++i)if(col[i]==-1) dfs(i,0);
calc(node[0],x),calc(node[1],x);
}
void Solve(int n){
for(int i=1;i<=2*n;++i) get_edges(i);
for(int i=1;i<=2*n;++i)if(to[i].size()==3){
for(int j=0;j<3;++j){
vector<int> vec={i};
for(int k=0;k<3;++k)if(k!=j)
vec.push_back(to[i][k]);
if(Query(vec)==1) {L[i]=to[i][j]; break;}
}
}
for(int i=1;i<=2*n;++i){
if(to[i].size()==1){
if(!vis[i] and !vis[to[i][0]])
Answer(i,to[i][0]),vis[i]=vis[to[i][0]]=1;
continue;
}
for(int j=0;j<3;++j){
if(L[i]==to[i][j] or L[to[i][j]]==i) continue;
if(!vis[i] and !vis[to[i][j]])
Answer(i,to[i][j]),vis[i]=vis[to[i][j]]=1;
}
}
}