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 <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <climits>
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
#include <utility>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <functional>

using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;

#define fst first
#define scd second
#define PB push_back
#define MP make_pair
#define rep(i,x) for(int i=0;i<(x);++i)
#define rep1(i,x) for(int i=1;i<=(x);++i)
#define rrep(i,x) for(int i=(x)-1;i>=0;--i)
#define rrep1(i,x) for(int i=(x);i>=1;--i)
#define FOR(i,a,x) for(int i=(a);i<(x);++i)
#define all(a) a.begin(),a.end()
#define rall(a) a.rbegin(),a.rend()
#define omajinai ios::sync_with_stdio(false);cin.tie(0)

template<typename T>bool chmax(T&a,T b){if(a<b){a=b;return true;}return false;}
template<typename T>bool chmin(T&a,T b){if(a>b){a=b;return true;}return false;}
template<typename T>T get(){T a;cin>>a;return a;}
template<typename T>T rev(T a){reverse(all(a));return a;}
template<typename T>istream&operator>>(istream&is,vector<T>&vec){rep(i,vec.size())is>>vec[i];return is;}
template<typename T>vector<T>&sort(vector<T>&a){sort(all(a));return a;}

const int inf = 1e9;
const ll linf = 3e18;
const double eps = 1e-9;

struct UF {
    vi data;
    void init(int n)
    {
        data.resize(n);
        fill(all(data), -1);
    }
    int root(int x)
    {
        return data[x] < 0 ? x : data[x] = root(data[x]);
    }
    void unite(int x, int y)
    {
        x = root(x);
        y = root(y);
        if (x == y) return;
        if (size(x) < size(y)) swap(x, y);
        data[x] += data[y];
        data[y] = x;
    }
    bool same(int x, int y)
    {
        return root(x) == root(y);
    }
    int size(int x)
    {
        return -data[x];
    }
    bool is_root(int x)
    {
        return x == root(x);
    }
};

UF uf;

int main()
{
    omajinai;

    int N, M; cin >> N >> M;

    uf.init(N + 1);

    rep1(i, M) {
        int a, b; cin >> a >> b;
        uf.unite(a, b);
    }

    int city = 0, village = 0;

    rep1(i, N) {
        if (uf.is_root(i)) {
            (uf.size(i) > 1 ? city : village)++;
        }
    }

    cout << abs(city - village) << endl;
}

C++: #include<bits/stdc++.h>
using namespace std;
#define r(i,n) for(int i=0;i<n;i++)
int n,m,a[2],x,y;
vector<int>v[1001];
bool used[1001];
int dfs(int p){
  int res=1;
  used[p]=1;
  r(i,v[p].size()){
    if(!used[v[p][i]]){
      res+=dfs(v[p][i]);
    }
  }
  return res;
}
int main(){
  cin>>n>>m;
  r(i,m){
    cin>>x>>y;
    x--,y--;
    v[x].push_back(y);
    v[y].push_back(x);
  }
  r(i,n)if(!used[i])a[dfs(i)>=2]++;
  cout<<abs(a[0]-a[1])<<endl;
}

C++: #include <bits/stdc++.h>
 
#define _overload(_1,_2,_3,name,...) name
#define _rep(i,n) _range(i,0,n)
#define _range(i,a,b) for(int i=(int)(a);i<(int)(b);++i)
#define rep(...) _overload(__VA_ARGS__,_range,_rep,)(__VA_ARGS__)
 
#define _rrep(i,n) _rrange(i,n,0)
#define _rrange(i,a,b) for(int i=(int)(a)-1;i>=(int)(b);--i)
#define rrep(...) _overload(__VA_ARGS__,_rrange,_rrep,)(__VA_ARGS__)
 
#define _all(arg) begin(arg),end(arg)
#define uniq(arg) sort(_all(arg)),(arg).erase(unique(_all(arg)),end(arg))
#define getidx(ary,key) lower_bound(_all(ary),key)-begin(ary)
#define clr(a,b) memset((a),(b),sizeof(a))
#define bit(n) (1LL<<(n))
 
// #define DEBUG
 
#ifdef DEBUG
    #define dump(...) fprintf(stderr, __VA_ARGS__)
#else
    #define dump(...)
#endif
 
template<class T>bool chmax(T &a, const T &b) { return (a<b)?(a=b,1):0;}
template<class T>bool chmin(T &a, const T &b) { return (b<a)?(a=b,1):0;}
 
using namespace std;
using ll=long long;
using vi=vector<int>;
using vll=vector<ll>;
 
const double EPS = 1e-10;
const double PI = acos(-1.0);
const ll inf =1LL << 62;
const ll mod=1000000007LL;
const int dx[4]={1,0,-1,0};
const int dy[4]={0,1,0,-1};
 
 
ll extgcd(ll a,ll b,ll& x,ll& y){x=1,y=0;ll g=a;if(b!=0) g=extgcd(b,a%b,y,x),y-=a/b*x;return g;}
ll ADD(const ll &a, const ll &b,const ll &mod) { return (a+b)%mod;}
ll SUB(const ll &a, const ll &b,const ll &mod) { return (a-b+mod)%mod;}
ll MUL(const ll &a, const ll &b,const ll &mod) { return (1LL*a*b)%mod;}
ll DIV(const ll &a, const ll &b,const ll &mod) {ll x,y; extgcd(b,mod,x,y);return MUL(a,(x+mod)%mod,mod);}
 
random_device rd;
mt19937 mt(rd());
uniform_int_distribution<int> dice(1,6);
uniform_real_distribution<double> score(0.0,10.0);
 
struct UnionFind {
    vector<int> data;
    UnionFind(int size) : data(size, -1) { }
    bool unionSet(int x, int y) {
        x = root(x); y = root(y);
        if (x != y) {
            if (data[y] < data[x]) swap(x, y);
            data[x] += data[y]; data[y] = x;
        }
        return x != y;
    }
    bool findSet(int x, int y) {
        return root(x) == root(y);
    }
    int root(int x) {
        return data[x] < 0 ? x : data[x] = root(data[x]);
    }
    int size(int x) {
        return -data[root(x)];
    }
};

int main(void){
    int n, m; cin >> n >> m;

    UnionFind uf(n);
    set<int> used;
    rep(loop, m){
        int a, b; cin >> a >> b;
        a--, b--;
        used.insert(a), used.insert(b);

        uf.unionSet(a, b);
    }

    set<int> roots;
    rep(i, n){
        if(used.find(i) == end(used)) continue;
        roots.insert(uf.root(i));
    }

    int res = abs(n - (int)used.size() - (int)roots.size());
    cout << res << endl;

    return 0;
}

C++: #include <iostream>
#include <set>

using namespace std;
const int MAX_N = 1010;

int Par[MAX_N];
int Rank[MAX_N];

void init(int n){
  for (int i = 0; i < n; i++){
    Par[i] = i;
    Rank[i] = 0;
  }
  return ;
}

int find(int x){
  if (Par[x] == x){
    return x;
  }else{
    return Par[x] = find(Par[x]);
  }
  
}

void unit(int x, int y){
  x = find(x);
  y = find(y);
  if (x == y)return ;

  if (Rank[x] < Rank[y]){
    Par[x] = y;
  }else{
    Par[y] = x;
    if (Rank[x] == Rank[y])Rank[x]++;
  }
}

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

int N,M;
int deg[MAX_N];
int main(){
  cin >> N >> M;
  init(N);
  for (int i = 0; i < M; i++){
    int a,b;
    cin >> a >> b;
    a--;
    b--;
    unit(a, b);
    deg[a]++;
    deg[b]++;
  }
  int village = 0;
  set<int> city;
  
  for (int i = 0; i < N; i++){
    if (deg[i]){
      int x = find(i);
      city.insert(x);
    }else{
      village++;
    }
    
  }
  //  cerr << village << " " << city.size() << endl;
  cout << abs(village - (int)city.size()) << endl;
}