func_code_string: #include <bits/stdc++.h>   using namespace std;   using ll = long long;   using pii = pair<int, int>;   const int N = 1e6 + 10;   struct UFS {     stack<pair<int *, int>> stk;     int fa[N], rnk[N];     inline void init(int n) {       for (int i = 0; i <= n; ++i) fa[i] = i, rnk[i] = 0;     }     inline int Find(int x) {       while (x ^ fa[x]) x = fa[x];       return x;     }     inline void Merge(int x, int y) {       x = Find(x), y = Find(y);       if (x == y) return;       if (rnk[x] <= rnk[y]) {         stk.push({fa + x, fa[x]});         fa[x] = y;         if (rnk[x] == rnk[y]) {           stk.push({rnk + y, rnk[y]});           rnk[y]++;         }       } else {         stk.push({fa + y, fa[y]});         fa[y] = x;       }     }     inline void Undo() {       *stk.top().first = stk.top().second;       stk.pop();     }   } ufs;   struct Edge {     int u, v;   };   int main() {     int n, m, k;     cin >> n >> m >> k;     vector<int> c(n + 1);     for (int i = 1; i <= n; i++) cin >> c[i];     vector<Edge> same_edges;     map<pair<int, int>, vector<Edge>> diff_edges;     for (int i = 0; i < m; i++) {       int u, v;       cin >> u >> v;       if (c[u] == c[v])         same_edges.push_back({u, v});       else {         if (c[u] > c[v]) swap(u, v);         diff_edges[{c[u], c[v]}].push_back({u, v});       }     }     vector<int> group_flag(k + 1, 1);     ufs.init((n + 1) * 2);     for (auto &[u, v] : same_edges) {       ufs.Merge(u * 2, v * 2 + 1);       ufs.Merge(u * 2 + 1, v * 2);       if (ufs.Find(u * 2) == ufs.Find(u * 2 + 1)) group_flag[c[u]] = 0;       if (ufs.Find(v * 2) == ufs.Find(v * 2 + 1)) group_flag[c[v]] = 0;     }     ll good_group_cnt = 0;     for (int i = 1; i <= k; i++)       if (group_flag[i]) good_group_cnt++;     ll cnt_fail = 0;     for (auto &[key, row] : diff_edges) {       if (!group_flag[key.first]) continue;       if (!group_flag[key.second]) continue;       int mark = (int)ufs.stk.size();       int flag = 1;       for (auto &[u, v] : row) {         ufs.Merge(u * 2, v * 2 + 1);         ufs.Merge(u * 2 + 1, v * 2);         if (ufs.Find(u * 2) == ufs.Find(u * 2 + 1)) flag = 0;         if (ufs.Find(v * 2) == ufs.Find(v * 2 + 1)) flag = 0;       }       if (!flag) cnt_fail++;       while ((int)ufs.stk.size() > mark) {         ufs.Undo();       }     }     ll ans = good_group_cnt * (good_group_cnt - 1) / 2;     ans = ans - cnt_fail;     cout << ans;   }   