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

// Problem: Graph with n nodes and m edges
// k nodes are "special" - cannot add edges between special nodes
// Find maximum edges we can add without connecting special nodes

struct DSU {
    vector<int> p;   // parent array
    vector<int> sz;  // size of each component
    
    DSU(int n = 0) {
        init(n);
    }
    
    void init(int n) {
        p.resize(n + 1);
        sz.assign(n + 1, 1);
        iota(p.begin(), p.end(), 0);  // each node is its own parent initially
    }
    
    // Find root of node u with path compression
    int find(int u) {
        while (p[u] != u) {
            p[u] = p[p[u]];  // compress path
            u = p[u];
        }
        return u;
    }
    
    // Merge two components using union by size
    void merge(int u, int v) {
        u = find(u);
        v = find(v);
        if (u == v) return;
        
        if (sz[u] < sz[v]) swap(u, v);  // make u the larger component
        p[v] = u;
        sz[u] += sz[v];
    }
};

class Solution {
public:
    long long maxEdgesToAdd(int n, vector<array<int, 2>>& e, vector<int>& sp) {
        // Build connected components from existing edges
        DSU d(n);
        for (auto& x : e) {
            d.merge(x[0], x[1]);
        }
        
        // Mark which components contain special nodes
        // (components inherit "special" property from their nodes)
        vector<bool> isSp(n + 1, false);
        for (int x : sp) {
            isSp[d.find(x)] = true;
        }
        
        // Collect all component roots
        vector<int> comp;
        for (int i = 1; i <= n; i++) {
            if (d.find(i) == i) {
                comp.push_back(i);
            }
        }
        
        // Max edges in a complete graph of k nodes: k*(k-1)/2
        auto maxE = [](long long k) {
            return k * (k - 1) / 2;
        };
        
        // If no special nodes, merge everything into one complete graph
        if (sp.empty()) {
            return maxE(n) - (long long)e.size();
        }
        
        // Find size of largest special component and total non-special nodes
        long long maxSp = 0;
        long long totNonSp = 0;
        
        for (int r : comp) {
            long long s = d.sz[r];
            
            if (isSp[r]) {
                maxSp = max(maxSp, s);
            } else {
                totNonSp += s;
            }
        }
        
        // Greedy strategy: 
        // - Merge ALL non-special components with the LARGEST special component
        //   (this maximizes edges since we create one big component)
        // - Keep other special components isolated (can't connect them anyway)
        long long maxPos = 0;
        
        // Count edges in the merged super-component
        // (largest special component + all non-special nodes)
        maxPos += maxE(maxSp + totNonSp);
        
        // Add edges within other special components (they stay separate)
        bool skip = false;
        for (int r : comp) {
            if (!isSp[r]) continue;
            
            long long s = d.sz[r];
            
            // Skip the largest special component (already counted above)
            if (s == maxSp && !skip) {
                skip = true;
                continue;
            }
            
            // Each remaining special component forms its own complete graph
            maxPos += maxE(s);
        }
        
        // Answer = max possible edges - edges already present
        return maxPos - (long long)e.size();
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n, m, k;
    cin >> n >> m >> k;
    
    // Input: m edges
    vector<array<int, 2>> e(m);
    for (int i = 0; i < m; i++) {
        cin >> e[i][0] >> e[i][1];
    }
    
    // Input: k special nodes
    vector<int> sp(k);
    for (int i = 0; i < k; i++) {
        cin >> sp[i];
    }
    
    Solution sol;
    cout << sol.maxEdgesToAdd(n, e, sp) << "\n";
    
    return 0;
}