[TASK]:
You will be given lines of pseudocode, your task is to write the corresponding C++ code. The pseudocode will provide detailed description of the c++ code line by line. The pseudocode is garanteed to be correct and complete.

[INSTRUCTION]:
The following libraries are already included in the code.
```cpp
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <cmath>
#include <cstring>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <list>
#include <fstream>
#include <climits>
#include <cassert>
#include <iomanip>
#include <sstream>
#include <bitset>
using namespace std;
```
Do not include them in your code again. Please surround your code with ```cpp and ``` markers. Note that the code should correspond to the pseudocode line by line.

[PSEUDOCODE]:
create int array num of size 1005
make integer array r of size 1005
declare fast taking in int x and returning int
    if r[x] is equal to x, return x
    return r[x] = find(r[x])
end of the block
declare setunion taking in ints x and y
    create int rx = find(x)
    make int ry = find(y)
    if rx is not equal to ry, set r[rx] to ry
end of the block
define the main function
    create ints n, m, and k
    make int array gov of size 1005
    make ints x and y
    read n, m, and k and while they are truthy
        set all contents of num to 0
        for i = 0 to n, set r[i] to i
        for i = 0 to k, read gov[i]
        for i = 1 to m
            read x and y
            call setunion with arguments x and y
        end of the block
        for i = 1 to n, increment num[find(i)]
        create int maxs = 0
        make integer left = n
        let int re = 0
        for i = 1 to k
            set num[gov[i]] to num[find(gov[i])
            set maxs to max of maxs and num[gov[i]]
            subtract num[gov[i]] from left
            add (num[gov[i]] - 1) * num[gov[i]] / 2 to re
        end of the block
        set re to re + (left + maxs) * (left + maxs - 1) / 2
        set re to re - maxs * (maxs - 1) / 2 + m
        print re
    end of the block
    return to indicate successful execution
end of the block

[CODE]:

int num[1005];
int r[1005];
int find(int x) {
    if (r[x] == x) return x;
    return r[x] = find(r[x]);
}
void setunion(int x, int y) {
    int rx = find(x);
    int ry = find(y);
    if (rx != ry) r[rx] = ry;
}
int main() {
    int n, m, k;
    int gov[1005];
    int x, y;
    while (cin >> n >> m >> k) {
        memset(num, 0, sizeof(num));
        for (int i = 0; i <= n; i++) { r[i] = i; }
        for (int i = 1; i <= k; i++) { cin >> gov[i]; }
        for (int i = 1; i <= m; i++) {
            cin >> x >> y;
            setunion(x, y);
        }
        for (int i = 1; i <= n; i++) { num[find(i)]++; }
        int maxs = 0;
        int left = n;
        int re = 0;
        for (int i = 1; i <= k; i++) {
            num[gov[i]] = num[find(gov[i])];
            maxs = max(maxs, num[gov[i]]);
            left -= num[gov[i]];
            re += (num[gov[i]] - 1) * num[gov[i]] / 2;
        }
        re += (left + maxs) * (left + maxs - 1) / 2;
        re -= maxs * (maxs - 1) / 2 + m;
        cout << re << endl;
    }
    return 0;
}