제출 #766732

#제출 시각아이디문제언어결과실행 시간메모리
766732qwerasdfzxcl조이터에서 친구를 만드는건 재밌어 (JOI20_joitter2)C++17
1 / 100
5032 ms14688 KiB
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

set<int> G[100100];
ll ans;

struct DSU{
	ll path[100100], sz[100100];
	set<int> st[100100], elem[100100];

	void init(int n){
		for (int i=1;i<=n;i++){
			path[i] = i;
			st[i].clear();
			elem[i].clear();
			elem[i].insert(i);
			sz[i] = 1;
		}
	}

	int find(int s){
		if (s==path[s]) return s;
		return path[s] = find(path[s]);
	}

	void merge(int x, int y){
		// printf(" merge %d %d\n", x, y);
		x = find(x), y = find(y);
		assert(x!=y);

		if (st[x].size() + elem[x].size() < st[y].size() + elem[y].size()) swap(x, y);

		ans -= (ll)st[x].size() * sz[x];
		ans -= (ll)st[y].size() * sz[y];
		ans -= sz[x] * (sz[x]-1);
		ans -= sz[y] * (sz[y]-1);
		// printf(" delete -> %lld\n", ans);

		for (auto p:st[y]) if (find(p)!=x){
			st[x].insert(p);
			G[find(p)].insert(x);
		} 

		for (auto p:elem[y]){
			auto iter = st[x].find(p);
			if (iter!=st[x].end()) st[x].erase(iter);
			elem[x].insert(p);
		}

		sz[x] += sz[y];
		ans += (ll)st[x].size() * sz[x];
		ans += sz[x] * (sz[x]-1);
		// printf(" add -> %lld (%d %d)\n", ans, (int)st[x].size(), sz[x]);

		path[y] = x;
	}

	void insert(int x, int y){
		y = find(y);
		if (st[y].find(x)!=st[y].end()) return;

		ans += sz[y];
		st[y].insert(x);
		G[find(x)].insert(y);
	}
}dsu;

void update(int x, int y){
	int cx = dsu.find(x), cy = dsu.find(y);
	if (cx==cy) return;
	
	if (G[cy].find(cx)!=G[cy].end()) dsu.merge(cx, cy);
	
	else dsu.insert(x, cy);
}

int adj[55][55];
int naive(int n, int x, int y){
	adj[x][y] = 1;

	while(true){
		int flag = 0;
		for (int i=1;i<=n;i++){
			for (int j=1;j<=n;j++){
				for (int k=1;k<=n;k++) if (i!=j && j!=k && i!=k){
					if (flag) break;
					if (adj[i][j] && adj[j][k] && adj[k][j] && !adj[i][k]){
						adj[i][k] = 1;
						flag = 1;
					}
				}
				if (flag) break;
			}
			if (flag) break;
		}

		if (!flag) break;
	}

	int ret = 0;
	for (int i=1;i<=n;i++){
		for (int j=1;j<=n;j++) ret += adj[i][j];
	}

	return ret;
}

int main(){
	int n, m;
	scanf("%d %d", &n, &m);

	dsu.init(n);

	for (int i=1;i<=m;i++){
		int x, y;
		scanf("%d %d", &x, &y);
		update(x, y);
		printf("%d\n", naive(n, x, y));
		// printf("%lld\n", ans);
	}
}

컴파일 시 표준 에러 (stderr) 메시지

joitter2.cpp: In function 'int main()':
joitter2.cpp:112:7: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  112 |  scanf("%d %d", &n, &m);
      |  ~~~~~^~~~~~~~~~~~~~~~~
joitter2.cpp:118:8: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  118 |   scanf("%d %d", &x, &y);
      |   ~~~~~^~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...