AtCoder ABC 177 D - Friends (400点)
https://gyazo.com/c9fa77d3cec7290d7b2e1f7596672488
考察履歴
グラフで友達関係を図示
XとYが友達、かつ、YとZが友達ならば、X とZも友達
要するに友達の友達も友達
つまり友達同士のグループを作り、最大グループのサイズが答えになる
最大グループのメンバを全員異なるグループにすれば、「同じグループの中に友達がいない」という状況が作れる
最大グループ以下のサイズのメンバは適当に割り振れば良い
このグループサイズを計算する方法がわからずコンテスト本番ではACできず。。解説AC ToDo幅優先探索の連結成分を調べても解答可能なよう ACコード
code:cpp
using namespace std;
typedef long long ll;
#define FOR(i,a,b) for(ll i=a;i<=(ll)(b);i++) #define REP(i,n) for(ll i=0;i<(ll)(n);i++) #define REPD(i,n) for(ll i=n-1;i>=0;i--) #define SORT(s) sort((s).begin(),(s).end()) // UnionFind
struct UnionFind{
//ノード情報のベクトル。
//各ノードは親のノードを指す。
//根なら木のサイズを負にして入れる。
vector<int> d;
//コンストラクタ dをn個の要素でそれぞれサイズ-1で初期化
UnionFind(int n=0): d(n,-1){}
//属する木のグループ番号を返す
//実態は属する木の根のノード番号
int find(int x){
}
//木の併合
//木のサイズが小さい方を大きい方にくっつける
//長いものにまかれにいく
//木が深くならなくなる
bool unite(int x, int y){
//所属するグループの検索
x = find(x); y = find(y);
//すでに所属グループが同じ
if(x==y) return false;
//xを大きいサイズのグループに設定する
//大きいグループxに小さいグループyをくっつける
//グループyの親をxにする
return true;
}
//ノードxとノードyが同じグループか判定する
bool same(int x, int y) { return find(x) == find(y);}
//所属するグループのサイズを返す
int size(int x) { return -dfind(x);} };
int main(){
ll N,M; cin >> N >> M;
UnionFind tree(N);
REP(i,M){
int a,b;
cin >> a >> b;
tree.unite(a-1,b-1);
}
int ans = 0;
REP(i,N){
ans = max(ans,tree.size(i));
}
cout << ans << endl;
return 0;
}
これは茶diffなのか。。。Union-Find知っていれば簡単ではあるが。。なるほど。