Go: package main

import (
    "fmt"
    "bufio"
    "strconv"
    "os"
    "strings"
    "math"
)

var rdr = bufio.NewReaderSize(os.Stdin, 1000000)

func readLine() string {
    buf := make([]byte, 0, 1000000)
    for {
        l, p, e := rdr.ReadLine()
        if e != nil {
            panic(e)
        }
        buf = append(buf, l...)
        if !p {
            break
        }
    }
    return string(buf)
}

func toInt(str string) int  {
    n, _ := strconv.Atoi(str)
    return n
}

func abs(a int) int {
    return int(math.Abs(float64(a)))
}

func getPar(x int, parent[1000]int) int {
    if parent[x] == x {
        return x
    } else {
        parent[x] = getPar(parent[x], parent)
        return parent[x]
    }
}

func main() {
    nm := strings.Split(readLine(), " ")
    n := toInt(nm[0])
    m := toInt(nm[1])
    var parent [1000]int
    for i := 0;i < n; i++ {
        parent[i] = i
    }


    for i := 0; i < m; i++ {
        ab := strings.Split(readLine(), " ")
        pa := getPar(toInt(ab[0]) - 1, parent)
        pb := getPar(toInt(ab[1]) - 1, parent)
        parent[pb] = pa
    }

    cities := make(map[int]int)
    villageCnt := 0
    for i := 0;i < n; i ++ {
        pi := getPar(i, parent)
        if i != pi {
            cities[pi] = 1
        } else {
            villageCnt ++
        }
    }
    cityCnt := len(cities)
    fmt.Println(abs(cityCnt * 2 - villageCnt))
}

C++: #include<bits/stdc++.h>
using namespace std;

struct UnionFind
{
  vector< int > data;

  UnionFind(int size)
  {
    data.assign(size, -1);
  }
  int Find(int k)
  {
    if(data[k] < 0) return(k);
    return(data[k] = Find(data[k]));
  }
  void unite(int x, int y)
  {
    x = Find(x);
    y = Find(y);
    if(x == y) return;
    data[x] += data[y];
    data[y] = x;
  }
  int Size(int k)
  {
    return(-data[Find(k)]);
  }
};
int main()
{
  int N, M;
  cin >> N >> M;
  UnionFind tree(N);
  for(int i = 0; i < M; i++) {
    int A, B;
    cin >> A >> B;
    --A, --B;
    tree.unite(A, B);
  }
  int mura = 0;
  int used[100] = {};
  for(int i = 0; i < N; i++) {
    int K = tree.Find(i);
    if(used[K]++) continue;
    if(tree.Size(K) == 1) ++mura;
    else --mura;
  }
  cout << abs(mura) << endl;
}

C++: #include <bits/stdc++.h>
#define rep(i, a, n) for(int i = a; i < n; i++)
#define repb(i, a, b) for(int i = a; i >= b; i--)
#define all(a) a.begin(), a.end()
#define int long long
using namespace std;

struct UF{
    vector<int> par;
    vector<int> sz;
    void init(int n){
        par.resize(n);
        sz.resize(n, 1);
        rep(i, 0, n) par[i] = i;
    }
    int find(int x){
        if(x == par[x]) return x;
        return par[x] = find(par[x]);
    }
    void unite(int x, int y){
        x = find(x); y = find(y);
        if(x == y) return;
        if(sz[x] < sz[y]) swap(x, y);
        sz[x] += sz[y];
        par[y] = x;
    }
};

signed main(){
    int n, m;
    cin >> n >> m;
    UF uf;
    uf.init(n);
    rep(i, 0, m){
        int a, b;
        cin >> a >> b;
        a--; b--;
        uf.unite(a, b);
    }
    int cnt = 0;
    set<int> st;
    rep(i, 0, n){
        st.insert(uf.find(i));
        if(uf.sz[uf.find(i)] == 1) cnt++;
    }
    cout << cnt << ' ' << st.size() << endl;
    cout << abs(st.size() - 2*cnt) << endl;
}

C++: #include<bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;++i)
#define FOR(i,a,b) for(int i=a;i<=b;++i)
#define LL long long
#define Fi first
#define Se second
using namespace std;
static const LL INF = 1LL<<61LL;
typedef pair<int,int> PII;

int N,M;
int flg[1010];
PII V[1010];
int cnt1;
int cnt2;
int main(){
    cin>>N>>M;
    cnt2=N;
    rep(i,M){
        int a,b;
        cin>>a>>b;
        flg[a]=1;
        flg[b]=1;
        V[i].Fi=max(a,b);
        V[i].Se=min(a,b);
    }
    sort(V,V+M);
    rep(i,M){
        bool was=false;
        rep(j,i){
            if(V[i].Fi==V[j].Fi||V[i].Se==V[j].Fi){ was=true; break; }
            if(V[i].Fi==V[j].Se||V[i].Se==V[j].Se){ was=true; break; }
        }
        if(!was)cnt1++;
    }
    //cout<<cnt1<<endl;
    FOR(i,1,N){
        if(flg[i])cnt2--;
    }
    cout<<abs(cnt1-cnt2)<<endl;
}

C++: #include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

template<int N>
struct UF {
    int ig[N];
    vector<int> gi[N];
    int gn;
    void init(int n = N) {
        for (int i = 0; i < n; i++) {
            ig[i] = i;
            gi[i] = {i};
        }
        gn = n;
    }
    void merge(int a, int b) {
        if (same(a, b)) return;
        gn--;
        int x = ig[a], y = ig[b];
        if ((int)gi[x].size() < (int)gi[y].size()) swap(x, y);
        for (int j: gi[y]) {
            ig[j] = x;
        }
        gi[x].insert(gi[x].begin(), gi[y].begin(), gi[y].end());
        gi[y].clear();
    }
    bool same(int a, int b) {
        return ig[a] == ig[b];
    }
};
const int MN = 1010;
UF<MN> uf;

int main() {
    int n, m;
    cin >> n >> m;
    uf.init(n);
    for (int i = 0; i < m; i++) {
        int a, b;
        cin >> a >> b;
        a--; b--;
        uf.merge(a, b);
    }
    int A = 0, B = 0;
    for (int i = 0; i < n; i++) {
        if (uf.gi[i].size() == 0) continue;
        if (uf.gi[i].size() == 1) B++;
        else A++;
    }
    printf("%d\n", abs(A-B));
}

C++: #include <bits/stdc++.h>
using namespace std;

#define for_(i,a,b) for(int i=(a);i<(b);++i)

int N, M;
vector< vector< int > > adj;
vector< bool > vis;

void dfs(int v, int& cnt) {
	if (vis[v]) return;
	vis[v] = true;
	++cnt;
	for (int u : adj[v]) dfs(u, cnt);
}

int main() {
	cin >> N >> M;
	
	adj.assign(N, vector< int >());
	
	for_(i,0,M) {
		int a, b;
		cin >> a >> b;
		--a; --b;
		adj[a].push_back(b);
		adj[b].push_back(a);
	}
	
	int A = 0, B = 0;
	vis.assign(N, false);
	
	for_(v,0,N) {
		if (vis[v]) continue;
		int cnt = 0;
		dfs(v, cnt);
		if (cnt == 1) ++A;
		else ++B;
	}
	
	cout << abs(B - A) << endl;
}

C++: #include <bits/stdc++.h>
typedef long long LL;
#define SORT(c) sort((c).begin(),(c).end())

#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)

using namespace std;
struct Unionfind {
  vector<int> size;
  vector<int> par;
  
  Unionfind( int n ) :  size(n, 1), par(n) {
    iota( par.begin() , par.end() , 0 );
  }
  
  int find( int x ) {
    if ( par[x] == x ) return x;
    return par[x] = find( par[x] );
  }
  
  bool unite( int x , int y ) {
    x = find(x);
    y = find(y);
    if ( x == y ) return false;
    
    if ( size[y] < size[x] ) swap( x , y );
    
    par[x] = y;
    size[y] += size[x];
    
    return true;
  }
  
  bool same( int x , int y ) {
    return find(x) == find(y);
  }
};

int main() {
  int n, q;
  cin >> n >> q;
  Unionfind uf(n);
  int x, y;
  REP(i,q) {
    cin >> x >> y;
    uf.unite(x-1, y-1);
  }
  set<int> sum,ci;
  REP(i,n){
    if(uf.find(i)==i) sum.insert(i);
    else ci.insert(uf.find(i));
  }
  cout << abs(int(sum.size())-2*int(ci.size())) << endl;
  return 0;
}

C++: #include<bits/stdc++.h>
using namespace std;
struct UnionFind{
  vector<int>parent,sizes;
  UnionFind(int n):parent(n),sizes(n,1){
    for(int i=0;i<n;++i)parent[i]=i;
  }
  int find(int x){
    return x==parent[x]?x:parent[x]=find(parent[x]);
  }
  void unite(int x,int y){
    if((x=find(x))==(y=find(y)))return;
    if(sizes[x]>sizes[y])swap(x,y);
    parent[y]=x;
    sizes[x]+=sizes[y];
    sizes[y]=0;
  }
  bool same(int x,int y){
    return find(x)==find(y);
  }
  int size(int x){
    return sizes[find(x)];
  }
};
main(){
  int n,m,a,b,x=0,y=0;
  cin>>n>>m;
  UnionFind UF(n);
  for(int i=0;i++<m;UF.unite(--a,--b))cin>>a>>b;
  for(int i=0;i<n;++i)UF.sizes[i]>1?x++:UF.sizes[i]-1?:y++;
  cout<<abs(x-y)<<endl;
}