100 10
87 73
15 71
14 33
1 4
20 80
65 67
36 36
25 4
22 21
7 97
 4 2
3 3
3 4
 5 4
3 3
4 4
5 5
1 2
 4 4
1 2
2 3
3 1
4 4
 4 3
1 1
2 3
3 4
 1000000 1
255765 255765
 4 3
1 2
2 3
4 4
 4 2
1 1
1 2
 3 3
1 1
2 2
3 3
 5 4
1 1
2 3
2 4
2 5
 4 5
1 4
3 4
1 2
2 3
2 4
 4 4
2 3
2 4
3 4
4 4
 10 9
8 10
3 10
2 8
9 3
4 8
1 10
7 9
5 4
7 3
 10 10
1 2
2 3
3 4
4 5
5 1
6 6
7 7
8 8
9 9
10 10
 5 5
1 4
3 4
1 2
2 3
2 4
 3 3
1 2
2 2
3 3
 5 3
1 1
2 2
3 3
 6 12
1 2
1 3
2 3
1 1
2 2
3 3
4 5
5 6
4 6
4 4
5 5
6 6
 4 4
1 2
2 3
1 3
4 4
 5 4
1 2
3 3
4 4
5 5
 7 13
6 7
2 7
3 7
4 3
5 2
1 4
7 7
3 1
5 5
3 3
1 5
2 6
6 6
 2 2
1 1
2 2
 5 5
1 1
2 2
3 3
4 4
5 5
 1 1
1 1
 7 3
1 1
3 3
6 6
 3 3
1 1
2 3
3 3

0 1 0 0 0 0 0 1 0 0 8 6 12 0 8 0 0 0 0 0 57 0 0 0 0 0
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.StringTokenizer;

public class d implements Runnable {

	public static void main(String[] args) {
		new Thread(null, new d(), "d", 1L << 26).start();
	}
	@Override
	public void run() {
		try {
			FastScanner in = new FastScanner(System.in);
			
			int n = in.nextInt();
			int m = in.nextInt();
			
			ArrayList<Edge>[] edges = new ArrayList[n];
			for(int i = 0; i < n; i++)
				edges[i] = new ArrayList<>();
			ArrayList<Edge> allEdges = new ArrayList<>();
			MagicComponents mc = new MagicComponents(n);
			//SCC scc = new SCC(n);
			boolean[] vis = new boolean[m * 2];
			boolean[] vvis = new boolean[n];
			long[] counts = new long[n];
			ArrayDeque<Integer> q = new ArrayDeque<>();
			for(int i = 0; i < m; i++) {
				int a = in.nextInt() - 1;
				int b = in.nextInt() - 1;
				if(i == 0) q.add(a);
				mc.addEdge(a, b);
				edges[a].add(new Edge(a, b, i));
				counts[a]++;
				if(a != b)
					counts[b]++;
				edges[b].add(new Edge(b, a, m + i));
				allEdges.add(new Edge(a, b, i));
			}
			vvis[q.peek()] = true;
			while(!q.isEmpty()) {
				int cur = q.poll();
				for(Edge e : edges[cur]) {
					//if(vis[e.id]) continue;
					vis[e.id]= true; 
					if(vvis[e.v]) continue;
					vvis[e.v] = true;
					q.add(e.v);
				}
			}
			boolean good = true;
			for(boolean a : vis)
				if(!a) good = false;
			if(!good) {
				System.out.println(0);
				return;
			}
			//mc.run();
			long ans = 0;
			for(int i = 0; i < n; i++) {
				long k = counts[i];
				ans += (k * (k - 1)) / 2;
			}
			
			System.out.println(ans);
		} catch(Throwable e) {
			e.printStackTrace();
			System.exit(-1);
		}
	}
	
	static class Edge {
		int u, v, id;
		public Edge(int uu, int vv, int idd) {
			u = uu; v = vv; id = idd;
		}
	}
	
	//# Bi-connected Components
	// Two-Connected Components
	// Articulation or cut points
	// Bridges //$
	static class MagicComponents { // Stack Trick!
	  int num, n, edges;
	  int[] dfsNum, low, visited;
	  ArrayList<Edge> bridges;
	  HashSet<Integer> cuts;
	  ArrayList<HashSet<Integer>> bccs, tccs; 
	  HashSet<Integer> tcc;
	  ArrayList<Edge>[] adj;
	  ArrayDeque<Integer> stack;
	  
	  class Edge {
	    int u, v, id;
	    public Edge(int U, int V, int i) {
	      u = U; v = V; id = i;
	    }
	  }
	  
	  MagicComponents(int N) {
	    adj = new ArrayList[n = N];
	    for (int i = 0; i < n; i++)
	      adj[i] = new ArrayList<Edge>();
	    edges = 0;
	  }  
	  
	  void addEdge(int u, int v) {
	    adj[u].add(new Edge(u, v, edges));
	    adj[v].add(new Edge(v, u, edges++));
	  }
	  
	  void run() {
	    visited = new int[n];
	    dfsNum = new int[n];
	    low = new int[n];
	    bridges = new ArrayList<Edge>();
	    cuts = new HashSet<Integer>();
	    bccs = new ArrayList<HashSet<Integer>>();
	    tccs = new ArrayList<HashSet<Integer>>();
	    tcc = new HashSet<Integer>();
	    stack = new ArrayDeque<Integer>();
	    num = 0;
	    
	    for (int i = 0; i < n; i++) {
	      if (visited[i] != 0) continue;
	      dfs(i, -1);
	      if (!tcc.isEmpty()) tccs.add(tcc);
	    }
	  }
	  
	  void dfs(int node, int par) {
	    dfsNum[node] = low[node] = num++;
	    visited[node] = 1;
	    int numChildren = 0;
	    for(Edge e : adj[node]) {
	      if(e.v == par) continue;
	      if(visited[e.v] == 0) {
	        ++numChildren;
	        stack.push(node);
	        dfs(e.v, node);
	        low[node] = Math.min(low[node], low[e.v]);
	        if(low[e.v] >= dfsNum[node]) {
	          if(dfsNum[node] > 0 || numChildren > 1)
	            cuts.add(node);
	          if(low[e.v] > dfsNum[node]) {
	            stack.push(e.v); bridges.add(e);
	            makeTCC(); pop(node); makeTCC();
	          } else pop(node);
	        }
	      } else if(visited[e.v] == 1) {
	        low[node] = Math.min(low[node], dfsNum[e.v]);
	        stack.push(node);
	      } 
	    }
	    visited[node] = 2;
	  }

	  //#
	  class StackState {
	    int node, parent, child, numChildren;
	    Edge e;
	    StackState(int n, int p, int c, int nc, Edge ed) {
	      node = n; parent = p; child = c; numChildren = nc;
	      e = ed;
	    }
	  }
	  void dfsItr(int start) {
	    ArrayDeque<StackState> s = new ArrayDeque<StackState>();
	    s.push(new StackState(start, -1, 0, 0, null));
	    
	    while(!s.isEmpty()) {
	      StackState st = s.pop();
	      
	      // First time on node
	      if(visited[st.node] == 0) {
	        dfsNum[st.node] = low[st.node] = num++;
	        visited[st.node] = 1;
	      }
	      
	      // At the end of all children
	      if(st.child == adj[st.node].size()) {
	        visited[st.node] = 2;
	      } else {
	        // Before dfs
	        if(st.e == null) {
	          st.e = adj[st.node].get(st.child);

	          // Visited or parent node
	          if(st.e.v == st.parent || visited[st.e.v] != 0) {
	            if(st.e.v != st.parent && visited[st.e.v] == 1) {
	              low[st.node] = Math.min(low[st.node], dfsNum[st.e.v]);
	              stack.push(st.node);
	            }
	            
	            ++st.child;
	            st.e = null;
	            s.push(st);
	          } else if(visited[st.e.v] == 0) { 
	            // Unvisited child
	            stack.push(st.node);
	            ++st.numChildren;
	            s.push(st);
	            s.push(new StackState(st.e.v, st.node, 0, 0, null));
	          }
	        } else { // After dfs
	          low[st.node] = Math.min(low[st.node], low[st.e.v]);
	          if(low[st.e.v] >= dfsNum[st.node]) {
	            if(dfsNum[st.node] > 0 || st.numChildren > 1)
	              cuts.add(st.node);
	            if(low[st.e.v] > dfsNum[st.node]) {
	              stack.push(st.e.v);
	              bridges.add(st.e);
	              makeTCC();
	              pop(st.node);
	              makeTCC();
	            } else
	              pop(st.node);
	          }
	          st.e = null;
	          s.push(st);
	        }
	      }
	    }
	  } //$
	  
	  void makeTCC() {
	    if (!tcc.isEmpty())
	      tccs.add(tcc);
	    tcc = new HashSet<Integer>();
	  }
	  
	  void pop(int u) {
	    HashSet<Integer> bcc = new HashSet<Integer>();
	    for (;;) {
	      bcc.add(stack.peek());
	      tcc.add(stack.peek());
	      if (stack.pop() == u) break;
	    }
	    bccs.add(bcc);
	  }
	  
	  //# Make sure to call run before calling this function.
	  // Function returns a new graph such that all two connected
	  // components are compressed into one node and all bridges
	  // in the previous graph are the only edges connecting the
	  // components in the new tree.
	  // nodeMapping is an integer array that will store the mapping
	  // for each node in the old graph into the new graph. //$
	  MagicComponents componentTree(int[] nodeMapping) {
	    boolean[] vis = new boolean[edges];
	    for(Edge e : bridges) vis[e.id] = true;
	    
	    int numComp = 0;
	    Arrays.fill(nodeMapping, -1);
	    for(int i = 0; i < n; ++i) {
	      if(nodeMapping[i] == -1) {
	        ArrayDeque<Integer> q = new ArrayDeque<Integer>();
	        q.add(i);
	        nodeMapping[i] = numComp;
	        while(!q.isEmpty()) {
	          int node = q.poll();
	          
	          for(Edge e : adj[node]) {
	            if(!vis[e.id] && nodeMapping[e.v] == -1) {
	              vis[e.id] = true;
	              nodeMapping[e.v] = numComp;
	              q.add(e.v);
	            }
	          }
	        }
	        ++numComp;
	      }
	    }
	    
	    MagicComponents g = new MagicComponents(numComp);
	    Arrays.fill(vis, false);
	    for(int i = 0; i < n; ++i) {
	      for(Edge e : adj[i]){
	        if(!vis[e.id] && nodeMapping[e.v] < nodeMapping[e.u]) {
	          vis[e.id] = true;
	          g.addEdge(nodeMapping[e.v], nodeMapping[e.u]);
	        }
	      }
	    }
	    
	    return g;
	  }
	}
	
	//@
	static class FastScanner {
	    BufferedReader br;
	    StringTokenizer st;
		
	    public FastScanner(InputStream i) {
	        br = new BufferedReader(new InputStreamReader(i));
	        st = new StringTokenizer("");
	    }
				
	    public String next() throws IOException {
	        if(st.hasMoreTokens())
	            return st.nextToken();
	        else
	            st = new StringTokenizer(br.readLine());
	        return next();
	    }

	    public int nextInt() throws IOException {
	        return Integer.parseInt(next());
	    }
	    //#
	    public long nextLong() throws IOException {
	        return Long.parseLong(next());
	    }
	    public double nextDouble() throws IOException {
	        return Double.parseDouble(next());
	    }
	    //$
	}

	
}
