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 <string>
#include <vector>
#include <algorithm>
#include <numeric>
#include <set>
#include <map>
#include <queue>
#include <iostream>
#include <sstream>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <cctype>
#include <cassert>
#include <limits>
#include <functional>
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define rer(i,l,u) for(int (i)=(int)(l);(i)<=(int)(u);++(i))
#define reu(i,l,u) for(int (i)=(int)(l);(i)<(int)(u);++(i))
#if defined(_MSC_VER) || __cplusplus > 199711L
#define aut(r,v) auto r = (v)
#else
#define aut(r,v) __typeof(v) r = (v)
#endif
#define each(it,o) for(aut(it, (o).begin()); it != (o).end(); ++ it)
#define all(o) (o).begin(), (o).end()
#define pb(x) push_back(x)
#define mp(x,y) make_pair((x),(y))
#define mset(m,v) memset(m,v,sizeof(m))
#define INF 0x3f3f3f3f
#define INFL 0x3f3f3f3f3f3f3f3fLL
using namespace std;
typedef vector<int> vi; typedef pair<int, int> pii; typedef vector<pair<int, int> > vpii; typedef long long ll;
template<typename T, typename U> inline void amin(T &x, U y) { if(y < x) x = y; }
template<typename T, typename U> inline void amax(T &x, U y) { if(x < y) x = y; }

struct UnionFind {
	vector<int> data;
	void init(int n) { data.assign(n, -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() {
	int N; int M;
	while(~scanf("%d%d", &N, &M)) {
		UnionFind uf; uf.init(N);
		rep(i, M) {
			int a; int b;
			scanf("%d%d", &a, &b), -- a, -- b;
			uf.unionSet(a, b);
		}
		int x = 0, y = 0;
		rep(i, N) if(uf.root(i) == i) {
			(uf.size(i) == 1 ? x : y) += 1;
		}
		int ans = abs(x - y);
		printf("%d\n", ans);
	}
	return 0;
}

C++: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

int n,m;
vector<int> G[1001];
bool used[1001];
int cnt=0;
int ans=0;

void dfs(int v){
	cnt++;
	used[v]=true;
	for(int i=0;i<G[v].size();i++){
		if(!used[G[v][i]]){
			dfs(G[v][i]);
		}
	}
}

int main(void){
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		a--;
		b--;
		G[a].push_back(b);
		G[b].push_back(a);
	}
	for(int i=0;i<n;i++){
		if(!used[i]){
			cnt=0;
			dfs(i);
			if(cnt==1)ans++;
			else ans--;
		}
	}
	printf("%d\n",abs(ans));
	return 0;
}

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;
        if(flg[a]==0)flg[a]=1;
        else if(flg[a])flg[a]=2;
        if(flg[b]==0)flg[b]=1;
        else if(flg[b])flg[b]=2;
        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++;
    }
    FOR(i,1,N){
        //cout<<i<<" "<<flg[i]<<endl;
        if(flg[i])cnt2--;
    }
    cout<<abs(cnt1-cnt2)<<endl;
}

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[1000] = {};
  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++: /*
 * c.cc: 
 */

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<deque>
#include<algorithm>
#include<numeric>
#include<utility>
#include<complex>
#include<functional>

using namespace std;

/* constant */

const int MAX_N = 1000;

/* typedef */

struct UFT {
  int links[MAX_N], ranks[MAX_N], sizes[MAX_N];

  void clear(int n) {
    for (int i = 0; i < n; i++) links[i] = i, ranks[i] = sizes[i] = 1;
  }
  UFT() {}
  UFT(int n) { clear(n); }

  int root(int i) {
    int i0 = i;
    while (links[i0] != i0) i0 = links[i0];
    return (links[i] = i0);
  }

  int rank(int i) { return ranks[root(i)]; }
  int size(int i) { return sizes[root(i)]; }
  bool same(int i, int j) { return root(i) == root(j); }

  int merge(int i0, int i1) {
    int r0 = root(i0), r1 = root(i1), mr;
    if (r0 == r1) return r0;
    if (ranks[r0] == ranks[r1]) {
      links[r1] = r0;
      sizes[r0] += sizes[r1];
      ranks[r0]++;
      mr = r0;
    }
    else if (ranks[r0] > ranks[r1]) {
      links[r1] = r0;
      sizes[r0] += sizes[r1];
      mr = r0;
    }
    else {
      links[r0] = r1;
      sizes[r1] += sizes[r0];
      mr = r1;
    }
    return mr;
  }
};

/* global variables */

UFT uft;

/* subroutines */

/* main */

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

  uft.clear(n);

  for (int i = 0; i < m; i++) {
    int ai, bi;
    cin >> ai >> bi;
    ai--, bi--;
    uft.merge(ai, bi);
  }

  int cn = 0, vn = 0;
  for (int i = 0; i < n; i++) {
    int ri = uft.root(i);
    if (ri == i) {
      if (uft.size(i) > 1) cn++;
      else vn++;
    }
  }

  printf("%d\n", abs(cn - vn));
  return 0;
}