ノートの互いに素セット
(wtcl脂肪含量ようのみCJ)
互いに素なセット、接続決意を解決します。せいぜいログ(n)のレベルを達成することができるはずです。これはああああああああああDFSとBFSよりもはるかに高速です。
名前が示すようにばらばらのセットは、それが二つに分かれています。
はじめに一般的な考え方
はい父親を表すID配列、と。その結果、
接続性の問題は彼らの父親は一つではない参照に変換されるかを決定。
コードの場合:
typedef long long ll;
ll n,m,x,y,z,id[N];
合併
例えば、xとyユニコムとの間の関係。
私たちが作るかもしれないとyは、xの父です。
だから、ID [x]はYを=;これらの言葉で人は簡単にあなたの息子になることができます。
コードの場合:
void unite(ll x,ll y){
ll xi=find(x),yi=find(y);
id[xi]=yi;
}
求めます
私たちは、関係に行くを見つけるために、彼の父の息子に従ってください:
あなたは、x [i]は父親を探している、[[i]はx]のお父さんはいつもいつも最後まで、見下ろしDを見つけることと等価です。
この男は、あなたの父の父の父の父の父の父の父の父の父の父の父の父の父の父の父の父の父の父の父の父の父の父であります父の父。
この人は、あなたの先祖を探している
コードについて:
ll find(ll x){
if(id[x]==x)return x;
return id[x]=find(id[x]);
}
通信を宣告
xiとyiの2つのポイントがあると仮定し
、その後xiは私の父の父yに等しい、あなたが接続されている場合。
全体的にテンプレートコードセクション(興奮):
#include<iostream>
#define N 100010
using namespace std;
typedef long long ll;
ll n,m,x,y,z,id[N];
ll find(ll x){
if(id[x]==x)return x;
return id[x]=find(id[x]);
}
void unite(ll x,ll y){
ll xi=find(x),yi=find(y);
id[xi]=yi;
}
int main(){
cin>>n>>m;
for(ll i=0;i<n;i++)id[i]=i;
while(m--){
cin>>z>>x>>y;
if(z==1) unite(x,y);
else if(z==2){
if(find(x)==find(y))cout<<"Y"<<endl;
else cout<<"N"<<endl;
}
}
return 0;
}
だから、意志数行、特に難しいことではない、右?