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<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#define loop(i,a,b) for(int i=a;i<b;i++)
#define rep(i,a) loop(i,0,a)
#define pro 100
using namespace std;

int parent[pro+1];

int find(int n){
	if(n==parent[n])return n;
	else find(parent[n]);
}

int main(){
	int n,m,city=0,town=0;
	cin>>n>>m;
	bool check[n+1];
	int a,b;
	loop(i,1,n+1)parent[i]=i;
	rep(i,m){
		cin>>a>>b;
		int top=find(a);
		parent[b]=top;
	}
	vector<int> vec[n+1];
	loop(i,1,n+1){
		vec[parent[i]].push_back(i);
	}
	loop(i,1,n+1){
		if(vec[i].size()==0)continue;
		if(vec[i].size()==1)town++;
		else city++;
	}
	cout<<abs(city-town)<<endl;
	return 0;
}

C++: #include<iostream>
#include<vector>
#define loop(i,a,b) for(int i=a;i<b;i++)
#define rep(i,a) loop(i,0,a)
#define pro 10000
using namespace std;

int abs(int n){
	if(n>0)return n;
	else return -1*n;
}

int main(){
	int vi, town, info;
	while(cin >> vi >> info){
		town = 1;
		int check[1005] = {0};
		rep(i,info){
			int a, b;
			cin >> a >> b;
			if(check[a] == check[b] && check[a] == 0){
				check[a] = town;
				check[b] = town;
				town++;
			}else if(check[a] == 0 && check[b] != 0 ){
					check[a] = check[b];
			}else if(check[a] != 0 && check[b] == 0){
					check[b] = check[a];
			}else if(check[a] != check[b]){
				for(int i = 1; i <= vi; i++){
					if(check[i] == check[a]) check[i] = check[b];
				}
			}
		}
		int m = 0, c = 0;
		for(int i = 1; i <= vi; i++){
			if(check[i] > 0){
				c++;
				for(int j = i + 1; j <= vi; j++){
					if(check[j] == check[i]) check[j] = -1;
				}
			}else if(check[i] == 0){
				m++;
			}
		}
		cout << abs(c - m) << endl;
	}
}

C++: #include <iostream>
#include <cmath>
#include <vector>
#include <set>
using namespace std;
class UnionFind{
    public:
    vector<int> par; //親は何番ですか
    vector<int> size; //集合の要素数を得る

    UnionFind(int n) : par(n),size(n,1){
        for(int i = 0; i < n; i++){
            par[i] = i; //最初の親は自分自身
        }
    }
    void init(int n){
        par.resize(n); 
        size.assign(n,1);
        for(int i = 0; i < n; i++){
            par[i] = i; //最初の親は自分自身
        }
    }

    int root(int x){ //根の検索を再帰的にやります
        if(par[x] == x) return x; //自分が根なら自分が根だと返す
        return par[x] = root(par[x]); //そうでないならxの親はxの親の親
    }

    bool unite(int x, int y){ //併合します
        x = root(x); //xの根
        y = root(y); //yの根
        if(x == y) return false; //根が同じならもう併合済み
        //併合するときは"小さい方"を"大きい方"に併合させる
        if(size[x] < size[y]) swap(x,y); 
        size[x] += size[y];
        par[y] = x; //併合するので親を変える
        return true;
    }

    bool isSame(int x,int y){ //2つの頂点が同じ集合に属するか
        return root(x) == root(y);
    }
    
    int getSize(int x){ //集合の要素の大きさを返します
        return size[root(x)];
    }
};

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n,m;
    cin >> n >> m;
    UnionFind uf(n);
    for(int i = 0; i < m; i++){
        int a,b;
        cin >> a >> b;
        a--; b--;
        if(!(uf.isSame(a,b))) uf.unite(a,b);
    }
    int cnt = 0;
    set<int> st;
    for(int i = 0; i < n; i++){
        int k = uf.root(i);
        if(uf.getSize(i) == 1) cnt++;
        else st.insert(k);
    }
    int sz = st.size();
    cout << abs(sz-cnt) << endl;
    return 0;
}

C++: #include <bits/stdc++.h>
using namespace std;
#define _MACRO(_1, _2, _3, NAME, ...) NAME
#define _repl(i,a,b) for(int i=(int)(a);i<(int)(b);i++)
#define _rep(i,n) _repl(i,0,n)
#define rep(...) _MACRO(__VA_ARGS__, _repl, _rep)(__VA_ARGS__)
#define mp make_pair
#define pb push_back
#define all(x) begin(x),end(x)
#define uniq(x) sort(all(x)),(x).erase(unique(all(x)),end(x))
#define fi first
#define se second
#define dbg(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
void _dbg(string){cerr<<endl;}
template<class H,class... T> void _dbg(string s,H h,T... t){int l=s.find(',');cerr<<s.substr(0,l)<<" = "<<h<<", ";_dbg(s.substr(l+1),t...);}
template<class T,class U> ostream& operator<<(ostream &o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream &o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

class UnionFind {
public:
  vector<int> par, rank;
  UnionFind(int sz) : par(sz, -1), rank(sz, 0){}
  int find(int x){
    if(par[x]<0) return x;
    else return par[x] = find(par[x]);
  }
  void unite(int x, int y){
    x=find(x); y=find(y);
    if(x==y) return;
    if(rank[x] < rank[y]) swap(x,y);
    par[x] += par[y];
    par[y] = x;
    if(rank[x]==rank[y]) rank[x]++;
  }
  inline bool same(int x, int y){ return find(x) == find(y); }
  inline int size(int x){ return -par[find(x)]; }
};

int main(){
  int n,m;
  cin>>n>>m;
  UnionFind uf(n);
  rep(i,m){
    int s,t;
    cin>>s>>t;
    s--;t--;
    uf.unite(s,t);
  }

  int ans = 0;
  rep(i,n){
    if(uf.size(i)==1) ans++;
    else if(uf.par[i]<0) ans--;
  }
  cout << abs(ans) << endl;

  return 0;
}

C++: #include <bits/stdc++.h>

using namespace std;

#define int long long
#define PB push_back
#define PPB pop_back
typedef pair<int, int> pii;
static const int INF = 1LL<<61;
static const int MAX_N = 1005;


class UF {
public:
    int n, par[MAX_N];

    void init(int pn) {
        n = pn;
        for (int i = 1; i <= n; ++i) {
            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;

        par[x] = y;
    }

    bool same(int x, int y) {
        return find(x) == find(y);
    }
};

UF uf;
int n, m;

int temp[MAX_N];

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> n >> m;
    uf.init(n);

    for (int i = 0; i < m; ++i) {
        int a, b;
        cin >> a >> b;
        uf.unite(a, b);
    }

    for (int i = 1; i <= n; ++i) {
        int t = uf.find(i);
        temp[t]++;
    }

    int city = 0, mura = 0;
    for (int i = 1; i <= n; ++i) {
        if (1 < temp[i]) city++;
        else if (temp[i] == 1) mura++;
    }

    cout << abs(mura - city) << endl;

    return 0;
}