In this HackerRank The Value of Friendship problem solution You are given q queries, where each query is in the form of an unordered list of m distinct direct friendships between n students. For each query, find the maximum value of total among all possible orderings of formed friendships and print it on a new line.

HackerRank The Value of Friendship problem solution


Problem solution in Python.

def grow(n):
  res = 0
  for i in range(1, n):
    res += i*(i+1)
    #print("-->", i, res)
  return res
  
def mark(x):
  z = x
  while z: z = z[0]
  if x is not z: x[0] = z
  return z

def mark2(x):
  z = x
  while z and type(z) == list: z = z[0]
  if x is not z: x[0] = z
  return z

  
T = int(input())
for t in range(T):
  n, m = map(int, input().split())
  work = [[] for i in range(n)] 
  lost = 0
  for i in range(m):
    u, v = map(int, input().split())
    u -= 1
    v -= 1
    mu = mark(work[u])
    mv = mark(work[v])
    if mu is not mv:
      mu.append(mv)
    else:
      lost += 1
      
  no = 1
  dic = {}
  for i in range(n):
    z = mark2(work[i])
    if not z:
      z.append(no)
      z = no
      no += 1
      dic[z] = 1
    else:
      dic[z] += 1

  res = 0
  cur = 0    
  for v in sorted(dic.values(), reverse = True):
    res += grow(v) + (v-1) * cur
    cur += v*(v-1)
    #print(v, cur, res) 
    
  res += lost * cur
  print(res)  

{"mode":"full","isActive":false}


Problem solution in Java.

import java.util.*;

public class Solution {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int t = in.nextInt();
        for(int a0 = 0; a0 < t; a0++){
            int n = in.nextInt();
            int m = in.nextInt();

            DisjointSets friendGroups = new DisjointSets(n);
            
            for(int a1 = 0; a1 < m; a1++){
                int x = in.nextInt();
                int y = in.nextInt();
                // your code goes here
                friendGroups.union(x - 1, y - 1);
            }
            
            List<Integer> groupSizes = friendGroups.setSizes();
            Collections.sort(groupSizes, Comparator.reverseOrder());

            long[] extra = new long[m];
            int idx = 0;
            for (int size : groupSizes) {
                for (int i = 1; i < size; i++) {
                    extra[idx++] = i;
                }
            }
            
            long totalFriendship = 0;
            long currentFriendship = 0;
            for (int i = 0; i < m; i++) {
                currentFriendship += 2L * extra[i];
                totalFriendship += currentFriendship;
            }
            System.out.println(totalFriendship);
        }
    }
    
    private static class DisjointSets {
        private int[] parent;
        private int[] size;
        
        public DisjointSets(int n) {
            parent = new int[n];
            size = new int[n];
            for (int i = 0; i < n; i++) {
                parent[i] = i;
                size[i] = 1;
            }
        }
        
        public void union(int a, int b) {
            int p = find(a);
            int q = find(b);
            if (p == q)
                return;
            if (size[p] < size[q]) {
                parent[p] = q;
                size[q] += size[p];
            }
            else {
                parent[q] = p;
                size[p] += size[q];
            }
        }
        
        public int find(int x) {
            while (x != parent[x]) {
                parent[x] = parent[parent[x]];
                x = parent[x];
            }
            return x;
        }
        
        public List<Integer> setSizes() {
            Set<Integer> sets = new HashSet<>();
            for (int x : parent)
                sets.add(find(x));
            List<Integer> sizes = new ArrayList<>();
            for (int x : sets)
                sizes.add(size[x]);
            return sizes;
        }
    }
}

{"mode":"full","isActive":false}


Problem solution in C++.

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <string>
#include <bitset>
#include <cstdio>
#include <limits>
#include <vector>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <fstream>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <unordered_map>

using namespace std;

vector<int> parent, setSz;


int find(int x)
{
	if (parent[x] == x)
		return x;
	return parent[x] = find(parent[x]);
}

int setunion(int a, int b)
{
	a = find(a);
	b = find(b);
	if (a == b)
		return setSz[a];
	if (setSz[a] < setSz[b])
		swap(a, b);
	parent[b] = a;
	setSz[a] += setSz[b];
	return setSz[a];
}

#define lint long long int


int main() {


	int t;
	cin >> t;
	for (int a0 = 0; a0 < t; a0++) {
		int n;
		int m;
		cin >> n >> m;

		parent.clear();
		parent.resize(n + 1);
		for (int i = 1; i <= n; i++)
			parent[i] = i;
		setSz.clear();
		setSz.resize(n + 1, 1);

		lint curFr = 0;
		lint res = 0;

		int same = 0;
	
		for (int a1 = 0; a1 < m; a1++) {
			int x;
			int y;
			cin >> x >> y;
			if (find(x) == find(y))
				same++;
			setunion(x, y);
			//lint oldSz1 = setSz[find(x)];
			//lint oldSz2 = setSz[find(y)];
			//lint newSz = setunion(x, y);
			//curFr += (newSz * (newSz - 1LL)) - (oldSz1 * (oldSz1 - 1LL)) - (oldSz2 * (oldSz2 - 1LL));
			//res += curFr;

			//cout << newSz << " " << curFr << endl;
		}
		set<int> clusters;
		vector<int> clusterSz;
		for (int i = 1; i <= n; i++)
		{
			int x = find(i);
			if (clusters.find(x) != clusters.end())
				continue;
			clusterSz.push_back(setSz[x]);
			clusters.insert(x);
		}
		sort(clusterSz.begin(), clusterSz.end());


		for (int i = clusterSz.size() - 1; i >= 0; i--)
		{
			for (int j = 2; j <= clusterSz[i]; j++)
			{
				curFr += j * (j - 1) - (j - 1) * (j - 2);
				res += curFr;
			}
		}
		res += curFr * same;


		cout << res << endl;
	}

	return 0;
}

{"mode":"full","isActive":false}


Problem solution in C.

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
#include <stdlib.h>

int n, m;
int graph[500002][2];  // [0]-neighbor node, [1]-next
int gend;
int nodeedge[100001];
int used[100001];

int bfs(int v, int *edgen) {
  int q[100001];
  int i, j, qe=1;
  q[0]=v;
  used[v]=1;
  *edgen=nodeedge[v];
  for (i=0; i<qe; i++) {
    for (j=q[i]; j && (v=graph[j][0]); j=graph[j][1]) {
      if (!used[v]) {
        q[qe++]=v;
        used[v]=1;
        *edgen+=nodeedge[v];
      }
    }
  }
  return qe;
}

static int cmp(const void *p1, const void *p2) {
  return *((const int *)p2)-*((const int *)p1);
}

uint64_t solve(void) {
  uint64_t total=0, tt=0, t;
  int noden[100001], edgen, rededgen=0;
  int i, nni=0;
  for (i=1; i<=n; i++) {
    if (used[i])
      continue;
    noden[nni]=bfs(i, &edgen);
    if (edgen)
      rededgen+=edgen-noden[nni++]+1;
  }
  qsort(noden, nni, sizeof(int), cmp);
  for (i=0; i<nni; i++) {
    t=noden[i];
    total+=(t*(t+1)*(t-1))/3+(t-1)*tt;
    tt+=t*(t-1);
  }
  total+=tt*rededgen;
  return total;
}

int main(void) {
  int i, q, u, v;
  scanf("%d\n", &q);
  while (q--) {
    scanf("%d%d\n", &n, &m);
    gend=n+1;
    for (i=0; i<m; i++) {
      scanf("%d%d\n", &u, &v);
      if (graph[u][0]) {
        graph[gend][0]=graph[u][0];
        graph[gend][1]=graph[u][1];
        graph[u][0]=v;
        graph[u][1]=gend++;
      } else {
        graph[u][0]=v;
      }
      if (graph[v][0]) {
        graph[gend][0]=graph[v][0];
        graph[gend][1]=graph[v][1];
        graph[v][0]=u;
        graph[v][1]=gend++;
      } else {
        graph[v][0]=u;
      }
      nodeedge[u]++;
    }
    printf("%"PRIu64"\n", solve());
    memset(graph, 0, sizeof(graph));
    memset(nodeedge, 0, sizeof(nodeedge));
    memset(used, 0, sizeof(used));
    gend=0;
  }
  return 0;
}

{"mode":"full","isActive":false}