CSES - Shared codeLink to this code:
https://cses.fi/paste/f3ea0f469366ebbd2b6c58/
#include <iostream>
#include <vector>
#include <unordered_map>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <unordered_set>
#include <map>
#include <queue>
#include <string>
#include <sstream>
using namespace std;
#define int long long
#define INF 1e18
#define pb push_back
#define FAST ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define ppb pop_back
#define lld long double
#define mod 1000000007
#define bn << '\n';
#define cbbn cout << '\n\n';
#define cbn cout << '\n';
#define debug cout << "HERE----------------------------\n";
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define vi vector<int>
#define vs vector<string>
#define vb vector<bool>
#define rep(i, a, n) for (int i = a; i < n; i++)
#define repr(i, n, a) for (int i = n; i >= a; i--)
#define pii pair<int, int>
#define vpi vector<pair<int, int>>
#define vvi vector<vector<int>>
#define vvpi vector<vector<pair<int, int>>>
#define sz(a) a.size()
#define clean(v,x) memset(v,x,sizeof(v));
template <typename T, typename T1> T amax(T &a, T1 b){if (b > a)a = b; return a;}
template <typename T, typename T1> T amin(T &a, T1 b){if (b < a)a = b;return a;}
template <typename T> std::istream &operator>>(std::istream &input, std::vector<T> &data){for (T &x : data)input >> x;return input;}
template <typename T> std::ostream &operator<<(std::ostream &output, const std::pair<T, T> &data){output << "(" << data.first << "," << data.second << ")"; return output;}
template <typename T> std::ostream &operator<<(std::ostream &output, const std::vector<T> &data){for (const T &x : data) output << x << " "; return output;}
// Custom Hash For Unordered set --> https://stackoverflow.com/questions/29855908/c-unordered-set-of-vectors
// Use this by -> unordered_set<vector<int>, VectorHash>mp;
//=============================================================================================================================
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////// DO NOT TOUCH BEFORE THIS LINE ///////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//=================================================SOLVE-ANS===================================================================
struct DSU {
//nodes are 1 base
int SetCnt, FirstSetCnt;
vector<int> par, sz;
//constructor
DSU (const int &x) {
SetCnt = x;
FirstSetCnt = x;
par.resize(x + 1);
sz.resize(x + 1);
fill(par.begin(), par.end(), -1);
fill(sz.begin(), sz.end(), 1);
}
//finding root of a vertex
int find(int x) {
return (par[x] == -1? x: par[x] = find(par[x]));
}
//merging two component
bool merge(int x, int y) {
int p1 = find(x), p2 = find(y);
SetCnt -= (p1 != p2);
if (sz[p1] > sz[p2])
swap(p1, p2);
if (p1 != p2)
sz[p2] += sz[p1];
return (p1 == p2? false: (par[p1] = p2) | 1);
}
//meging two DSU (adding every edge in second DSU to first DSU) ---> O(n.log*(n))
bool joinDSU(DSU &x) {
if (x.size() != FirstSetCnt)
return false;
for (int i = 1; i <= FirstSetCnt; i++) {
int p1 = find(i), p2 = x.find(i);
if (p1 != p2)
merge(p1, p2);
}
return true;
}
//clear DSU
void clear() {
fill(par.begin(), par.end(), -1);
fill(sz.begin(), sz.end(), 1);
SetCnt = FirstSetCnt;
}
//number of nodes in component of node x
int size_cmp(const int &x) {
return sz[find(x)];
}
//number of components
int num_cmp() {
return SetCnt;
}
//number of nodes
int size() {
return FirstSetCnt;
}
};
void Here_We_Go()
{
int n,m;
cin>>n>>m;
vs v(n);
cin>>v;
DSU a(n*m + 10);
int ans=0;
rep(i,0,n)
{
rep(j,0,m)
{
if(v[i][j]=='.')
{
int p1=a.find(i*m + j);
ans++;
if(i-1>=0 && v[i-1][j]=='.')
{
int p2=a.find((i-1)*m + j);
if(p1!=p2)
{
ans--;
a.merge(i*m +j,(i-1)*m + j );
}
}
if(i+1<n && v[i+1][j]=='.')
{
int p2=a.find((i+1)*m + j);
if(p1!=p2)
{
ans--;
a.merge(i*m +j,(i+1)*m + j );
}
}
if(j-1>=0 && v[i][j-1]=='.')
{
int p2=a.find((i)*m + j-1);
if(p1!=p2)
{
ans--;
a.merge(i*m +j,(i)*m + j-1 );
}
}
if(j+1<m && v[i][j+1]=='.')
{
int p2=a.find((i)*m + j+1);
if(p1!=p2)
{
ans--;
a.merge(i*m +j,(i)*m + j+1 );
}
}
}
}
}
cout<<ans bn
}
int32_t main()
{
FAST
// #ifndef ONLINE_JUDGE
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
// #endif
int tc = 1;
//cin >> tc;
rep(i, 1, tc + 1)
{
//cout << "Case #" << i << ": ";
Here_We_Go();
}
}