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++: #define _USE_MATH_DEFINES

#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
#include<iostream>
#include<fstream>
#include<iomanip>

using namespace std;

int N, M;
int data[1001][1001];
int check[1001];

int grp = 1;

int back(int cur) {
	int cnt = 1;
	for (int i = 1; i <= N; ++i) {
		if (data[cur][i] == -1) {
			if (!check[i]) {
				check[i] = true;
				data[cur][i] = data[i][cur] = grp;
				cnt += back(i);
			}
			data[cur][i] = data[i][cur] = grp;
		}
	}
	return cnt;
}

int main(){
	int a, b;
	scanf("%d%d", &N, &M);
	for (int i = 0; i < M; ++i){
		scanf("%d%d", &a, &b);
		data[a][b] = data[b][a] = -1;
	}
	int shi = 0;
	for (int i = 1; i <= N; ++i) {
		if (check[i]) continue;
		check[i] = 1;
		int res = back(i);
		if (res > 1) {
			grp++;
			shi += res;
		}
	}
	grp--;
	printf("%d\n", abs((N - shi) - grp));
	return 0;
}

C++: #include<vector>

class UnionFind{
public:
    UnionFind(int N):parent(N), rank(N,0), size(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]);
    }
    bool same(int x,int y){
        return find(x)==find(y);
    }
    void unite(int x,int y){
        x=find(x), y=find(y);
        if(x==y) return;
        if(rank[x]==rank[y]) parent[y]=x, rank[x]++;
        else{
            if(rank[x]<rank[y]) std::swap(x,y);
            parent[y]=x;
        }
        size[x]+=size[y];
        size[y]=0;
    }
    int getParentSize(int x){
        return size[find(x)];
    }
    int getSize(int x){
        return size[x];
    }
private:
    std::vector<int> parent, rank, size;
};

#include<cmath>
#include<iostream>
using namespace std;
int main(){
    int N,M;
    cin>>N>>M;
    UnionFind UF(N);
    for(int i=0;i<M;++i){
        int a,b;
        cin>>a>>b;
        UF.unite(--a,--b);
    }
    int x=0,y=0;
    for(int i=0;i<N;++i) UF.getSize(i)>1?x++:UF.getSize(i)-1?:y++;
    cout<<abs(x-y)<<endl;
}

C++: #include <iostream>
#include <vector>
#include <cmath>
#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;
vector<int> G[1003];
int N,M;
bool visited[1003];

void dfs(int v,int &cnt) {
    if(visited[v]) return;

    cnt++;
    visited[v]=true;
    for(auto u:G[v]) {
        if(visited[u]) continue;
        dfs(u,cnt);
    }

}

int main() {
    cin>>N>>M;
    rep(i,M) {
        int a,b;
        cin>>a>>b;
        a--,b--;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    int ans=0;
    rep(i,N) {
        if(visited[i]) continue;
        int cnt=0;
        dfs(i,cnt);
        if(cnt==1) ans++;
        else ans--;
    }
    cout<<abs(ans)<<endl;
    return 0;
}

C++: #include<iostream>
#include<vector>
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 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>
using namespace std;
bool u[1010];
vector<int> v[1010];
int dfs(int x,bool f) {
  u[x]=1;
  for(int i=0; i<v[x].size(); i++) {
    if(!u[v[x][i]]) f=0,dfs(v[x][i],f);
  }
  return f;
}

int main() {
  int n,m;
  cin >> n >> m;
  for(int i=0,x,y; i<m; i++) {
    cin >> x >> y;
    v[x].push_back(y);
    v[y].push_back(x);
  }
  int x=0,y=0;
  for(int i=1; i<=n; i++) {
    if(!u[i]) dfs(i,1)?x++:y++;
  }
  cout << abs(x-y) << endl;
  return 0;
}

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

using namespace std;

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

class UF {
public:
	int n; vector<int> a;
	UF(int n) : n(n), a(n, -1) {}
	int find(int x) {
		return a[x] < 0 ? x : (a[x] = find(a[x]));
	}
	bool unite(int x, int y) {
		x = find(x), y = find(y);
		if (x == y) return false;
		if (a[x] > a[y]) swap(x, y);
		a[x] += a[y];
		a[y] = x;
		n--;
		return true;
	}
	int size(int x) {
		return -a[find(x)];
	}
};

int main() {
	int n, m; scanf("%d%d", &n, &m);
	UF uf(n);
	FOR(i, m) {
		int a, b; scanf("%d%d", &a, &b);
		a--; b--;
		uf.unite(a, b);
	}
	int ans = 0;
	FOR(i, n) if (uf.find(i) == i) {
		if (uf.size(i) == 1) ans++;
		else ans--;
	}
	cout << abs(ans) << endl;
}

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


vector<long long int>UF;

long long int pearent( long long int now ) {
	if( UF[now] == now ) {
		return now;
	} else {
		return UF[now] = pearent( UF[now] );
	}
}

void merge( long long int x, long long int y ) {
	UF[pearent( x )] = UF[pearent( y )];
}

int main() {
	long long int N, M;
	cin >> N >> M;
	UF = vector<long long int>( N );
	vector<bool>qwe( N );
	for( size_t i = 0; i < N; i++ ) {
		UF[i] = i;
	}
	for( size_t i = 0; i < M; i++ ) {
		long long int a, b;
		cin >> a >> b;
		a--; b--;
		qwe[a] = 1;
		qwe[b] = 1;
		merge( a, b );
	}
	long long int ans = 0;
	long long int num = 0;
	for( size_t i = 0; i < N; i++ ) {

		if( UF[i] == i ) {
			ans++;
			if( qwe[i] == false ) {
				num++;
			}
		}
	}
	cout << abs( (ans - num) - num ) << endl;
}