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.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ProblemC {
	
	public static void main(String[] args) throws IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter out = new PrintWriter(System.out);

		String[] nm = in.readLine().split(" ");
		int n = Integer.valueOf(nm[0]);
		int m = Integer.valueOf(nm[1]);
		int[][] graph = new int[n][];
		int[] deg = new int[n];
		int[][] edges = new int[m][3];
		for (int i = 0 ; i < m ; i++) {
			String[] ab = in.readLine().split(" ");
			int a = Integer.valueOf(ab[0])-1;
			int b = Integer.valueOf(ab[1])-1;
			deg[a]++;
			deg[b]++;
			edges[i][0] = a;
			edges[i][1] = b;
		}
		for (int i = 0 ; i < n ; i++) {
			graph[i] = new int[deg[i]];
		}
		for (int i = 0 ; i < m ; i++) {
			int a = edges[i][0];
			int b = edges[i][1];
			graph[a][--deg[a]] = b;
			graph[b][--deg[b]] = a;
		}
		for (int i = 0 ; i < n ; i++) {
			Arrays.sort(graph[i]);
		}
		
		long alice = 0;
		for (int i = 0 ; i < m ; i++) {
			int a = edges[i][0];
			int b = edges[i][1];
			int al = graph[a].length;
			int bl = graph[b].length;
			int bi = 0;
			for (int ai = 0 ; ai < al ; ai++) {
				while (bi < bl && graph[a][ai] > graph[b][bi]) {
					bi++;
				}
				if (bi < bl && graph[a][ai] == graph[b][bi]) {
					alice++;
					edges[i][2]++;
				}
			}
		}
		alice /= 3;
		
		
		long bob = 0;
		
		UnionFind uf = new UnionFind(n);
		for (int i = 0 ; i < m ; i++) {
			uf.unite(edges[i][0], edges[i][1]);
		}
		int[][] gcnt = new int[n][2];
		for (int i = 0 ; i < n ; i++) {
			int gi = uf.find(i);
			gcnt[gi][0]++;
			gcnt[gi][1] += graph[i].length;
		}
		List<Group> groups = new ArrayList<Group>();
		int twoormore = 0;
		for (int i = 0 ; i < n ; i++) {
			if (gcnt[i][0] >= 2) {
				groups.add(new Group(gcnt[i][0], gcnt[i][1]));
				twoormore += gcnt[i][0];
			}
		}
		if (n - twoormore >= 1) {
			groups.add(new Group(n - twoormore, 0));
		}
		
		int gl = groups.size();
		
		// type : A,B,C
		long[][] dp = new long[gl+1][5];
		dp[0][0] = 1;
		for (int i = 0 ; i < gl ; i++) {
			Group grp = groups.get(i);
			for (int a = 0 ; a <= 3 ; a++) {
				// use it
				dp[i+1][a+1] += dp[i][a] * grp.n;
				
				// dont use it
				dp[i+1][a] += dp[i][a];
			}
		}
		bob += dp[gl][3];
		debug("abc",dp[gl][3]);
		
		// type : A,A,B
		long aab = 0;
		for (int i = 0 ; i < gl ; i++) {
			Group grp = groups.get(i);
			long tedge = 1L * grp.n * (grp.n - 1) / 2;
			long ledge = tedge - grp.e / 2;
			aab += ledge * (n - grp.n);
		}
		bob += aab;
		debug("aab", aab);
		
		// type : A,A,A
		long aaa = 0;
		for (int i = 0 ; i < gl ; i++) {
			Group grp = groups.get(i);
			long totalT = grp.n * (grp.n-1) * (grp.n-2) / 6;
			aaa += totalT;
		}
		debug(aaa);
		aaa -= alice;
		debug(aaa);
		
		long twoedges = 0;
		for (int i = 0 ; i < m ; i++) {
			int a = edges[i][0];
			int gn = gcnt[uf.find(a)][0];
			int onlyone = gn - edges[i][2] - 2;
			twoedges += onlyone;
		}
		twoedges /= 2;
		aaa -= twoedges;
		debug("aaa", aaa);
		bob += aaa;
		
		out.println(alice + bob);
		out.flush();
	}
	

    static class UnionFind {
         int[] parent, rank;
         UnionFind(int n) {
              parent = new int[n];
              rank = new int[n];
              for (int i = 0 ; i < n ; i++) {
                   parent[i] = i;
                   rank[i] = 0;
              }
         }
        
         int find(int x) {
              if (parent[x] == x) {
                   return x;
              }
              parent[x] = find(parent[x]);
              return parent[x];
         }
        
         void unite(int x, int y) {
              x = find(x);
              y = find(y);
              if (x == y) {
                   return;
              }
              if (rank[x] < rank[y]) {
                   parent[x] = y;
              } else {
                   parent[y] = x;
                   if (rank[x] == rank[y]) {
                        rank[x]++;
                   }
              }
         }
         boolean issame(int x, int y) {
              return (find(x) == find(y));
         }
    }
	
    
    static final class Group {
    	long n = 0;
    	long e = 0;
    	Group(int a, int b) {
    		n = a;
    		e = b;
    	}
    	
    }

	public static void debug(Object... o) {
		//System.err.println(Arrays.deepToString(o));
	}
}

