3 3
1 2
3 1
2 3
 2 0
 10 17
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
1 10
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
 2 1
1 2
 8 13
1 2
2 3
3 4
4 1
2 4
1 3
5 6
6 7
7 8
8 5
6 8
5 7
1 8
 3 2
1 2
2 3
 10 9
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
1 10
 10 40
1 3
2 6
9 10
4 6
1 2
1 8
6 10
3 6
1 4
5 7
3 8
3 9
4 5
3 7
8 9
5 9
5 6
2 3
3 4
1 6
4 8
3 10
5 10
2 8
2 10
4 7
1 10
1 7
4 10
5 8
8 10
7 9
6 8
2 7
4 9
6 9
7 8
6 7
1 5
2 9
 10 9
1 2
2 3
3 1
4 5
5 6
6 7
7 4
4 6
5 7
 1000000 0
 8 11
1 2
1 3
1 4
2 3
2 7
7 4
4 2
7 5
8 1
1 7
7 8
 9 9
1 2
2 3
3 1
4 5
5 6
6 4
7 8
8 9
9 7
 15 14
1 2
1 3
1 4
1 5
2 6
2 7
7 8
7 9
3 10
10 11
4 12
12 13
13 14
13 15
 10 17
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
1 10
2 3
2 4
2 5
2 6
2 7
2 8
2 9
2 10
 9 12
1 2
2 3
3 1
1 4
4 5
5 1
1 6
6 7
7 1
1 8
8 9
9 1
 3 1
1 2
 10 5
5 7
4 8
9 10
7 10
6 10
 15 15
1 2
1 3
1 4
1 5
2 6
2 7
7 8
7 9
3 10
10 11
4 12
12 13
13 14
13 15
15 1
 4 3
1 2
2 3
3 1
 10 30
4 9
4 6
1 2
8 10
7 8
4 7
1 8
6 7
5 6
1 5
7 9
1 7
8 9
7 10
9 10
3 9
2 7
5 7
5 9
2 8
2 9
5 8
3 10
1 6
3 6
2 10
6 8
3 4
2 5
4 5
 4 3
1 2
1 3
1 4
 4 6
1 2
2 3
3 4
4 1
1 3
2 4
 10 9
1 2
1 3
1 4
2 5
5 6
2 7
3 8
3 9
9 10
 10 10
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 1
 3 0
 6 6
1 2
2 3
3 1
4 5
5 6
6 4
 10 0
 9 15
1 2
2 3
3 1
1 4
4 5
5 1
1 6
6 7
7 1
1 8
8 9
9 1
2 9
7 4
2 8
 4 0
 1 0

1
 0
 43
 0
 8
 0
 84
 82
 63
 166666166667000000
 21
 30
 292
 64
 36
 0
 84
 284
 1
 37
 1
 4
 59
 50
 1
 2
 120
 28
 4
 0

import java.io.*;
import java.util.*;

public class B {
	public static void main (String[] args) { new B(); }

	int[] par, us, vs, subAll;
//	BitSet used;
	byte[] used;
	int[][] adj, ids;
	
	B() {
		FastestScanner fs = new FastestScanner();
//		try { fs = new FastestScanner("testdata.out"); } catch (Exception e) {}
		System.err.println("");

		int n = fs.nextInt(), m = fs.nextInt();
		subAll = new int[n];
		readGraph(fs, n, m);
		
//		used = new BitSet(m);
		used = new byte[m];
		par = new int[n]; Arrays.fill(par, -2);
		
		int[] bfs = new int[n];
		for(int i = 0; i < n; i++) if(par[i] == -2) {
			par[i] = -1;
			int tail = 0;
			bfs[tail++] = i;
			for(int ii = 0; ii < tail; ii++) {
				int now = bfs[ii];
				for(int jj = 0; jj < adj[now].length; jj++) {
					int v = adj[now][jj], id = ids[now][jj];
					subAll[now] += adj[v].length;
					if(par[v] != -2) continue;
					used[id] = 1;
					par[v] = now;
					bfs[tail++] = v;
				}
			}
		}
		long alice = 0;
		int[] anchor = new int[n];
		
		for(int i = 0; i < m; i++) {
			if(used[i] == 1) continue; 
			int u = us[i], v = vs[i];
			
			int good = 0;
			int pu = par[u], pv = par[v];
			if(pu != -1 && par[pu] == v) {
				good = 1;
			}
			else if(pv != -1 && par[pv] == u) {
				good = 2;
			}
			else if(pu == pv && pu != -1) {
				good = 3;
			}
			
			int j, pj;
			if(good != 0) {
				++alice;
				if(good < 3) {
					j = good == 1 ? u : v;
					pj = par[j];
					++anchor[j]; ++anchor[pj];
					++anchor[ par[pj] ];
				}
				else {
					++anchor[u]; ++anchor[v]; ++anchor[pu];
				}
			}
		}
		
		long bob = 0;
		for(int i = 0; i < n; i++) {
			long P = n - adj[i].length-1;
			int E = m - subAll[i];
			E += anchor[i];
			long add = ((P*(P-1))>>1) - E;
			bob += add;
		}
		bob /= 3;
		
		System.out.println(alice+bob);
	}
	
	void readGraph(FastestScanner fs, int n, int m) {
		adj = new int[n][];
		ids = new int[n][];
		int[] deg = new int[n];
		us = new int[m]; vs = new int[m];
		for(int i = 0; i < m; i++) {
			us[i] = fs.nextInt()-1;
			vs[i] = fs.nextInt()-1;
			deg[us[i]]++; deg[vs[i]]++;
		}
		for(int i = 0; i < n; i++) {
			adj[i] = new int[deg[i]];
			ids[i] = new int[deg[i]];
			deg[i] = 0;
		}
		for(int i = 0; i < m; i++) {
			int u = us[i], v = vs[i];
			adj[u][deg[u]] = v; ids[u][deg[u]++] = i;
			adj[v][deg[v]] = u; ids[v][deg[v]++] = i;
		}
	}
	
	class FastestScanner {
		public int BS = 1<<25;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;

		public FastestScanner() {
			in = new BufferedInputStream(System.in, BS);
		}

		public FastestScanner(String s) {
			try {
				in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
			}
			catch (Exception e) {
				in = new BufferedInputStream(System.in, BS);
			}
		}

		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}                
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}

		public int nextInt() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			int res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}

		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}
		
		public int[] nextIntArray(int n) {
			int[] res = new int[n];
			for(int i = 0; i < n; i++) res[i] = nextInt();
			return res;
		}
		
	}

}