@Override
    public Object solve() {

        final int max = 10000000;

        final boolean[] sieve = new boolean[max+1];
        final Set<Integer> primes = new HashSet<Integer>(max/2);
        long sum = 0;
        
        int i = 1;
        
        for (int q = 1; (q += (i++ << 1) + 1) <= max; ) {
            if (!sieve[i]) {
                primes.add(i);
                sum += i;
                for (int j = q; j <= max; j += i) sieve[j] = true;
            }
        }
        for ( ; i <= max; ++i) {
            if (!sieve[i]) {
                primes.add(i);
                sum += i;
            }
        }
        
        final Queue<int[]> queue = new PriorityQueue<int[]>(1, new Comparator<int[]>() {

            @Override
            public int compare(int[] o1, int[] o2) { return Integer.compare(o1[1], o2[1]); }
            
        });
        
        queue.add(new int[] {2, 2});
        primes.remove(2);
        sum -= 2;
        
        for (int[] current; (current = queue.poll()) != null; ) {
            for (int connectedPrime : connectedPrimes(current[0], primes)) {
                
                final int[] node = {connectedPrime, max(connectedPrime, current[1])};
                
                if (node[1] <= node[0]) sum -= connectedPrime;
                queue.add(node);
                primes.remove(connectedPrime);
            }
        }

        return sum;
    }