jiahuimbzuai/CoQuIR huggingface dataset:
//  [java]
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        FastScanner fs=new FastScanner();
        int n=fs.nextInt();
        int m=fs.nextInt();
        HashMap<Integer, HashSet<Integer>>map=new HashMap<Integer, HashSet<Integer>>();
        for(int i=1;i<=n;i++)map.put(i,new HashSet<>());
        for (int tt=0; tt<m; tt++){
            int a=fs.nextInt();
            int b=fs.nextInt();
            map.get(a).add(b);
            map.get(b).add(a);
        }
        int max = 0;
        
        Set<Integer> seen = new HashSet<Integer>();
        for(int j = 1;j<=n;j++){

            if (!seen.contains(j)){

                Stack<Integer> dfs = new Stack<Integer>();
                dfs.add(j);
                Set<Integer> tempseen = new HashSet<Integer>();
                while(!dfs.isEmpty()){
                    int vertex = dfs.pop();
                    for(int child : map.get(vertex)){
                        if (!tempseen.contains(child))
                            dfs.add(child);
                    }
                    tempseen.add(vertex);
                    seen.add(vertex);
                }
                max=Math.max(tempseen.size(), max);
            }

        }
        System.out.println(max);



    }
    static class FastScanner {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer("");
        String next() {
            while (!st.hasMoreTokens())
                try {
                    st=new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }
        int[] readArray(int n) {
            int[] a=new int[n];
            for (int i=0; i<n; i++) a[i]=nextInt();
            return a;
        }
        long nextLong() {
            return Long.parseLong(next());
        }
    }
}
//  [java]
import java.util.*;
import java.io.*;
public class Main {

	public static void main(String[] args) throws Exception{
		int num = 998244353;

		// TODO Auto-generated method stub
 		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
 		PrintWriter out = new PrintWriter(System.out);
 		
	 	StringTokenizer st = new StringTokenizer(bf.readLine());
	 	int n = Integer.parseInt(st.nextToken());
	 	int m = Integer.parseInt(st.nextToken());
	 	Map<Integer, Set<Integer>> graph = new HashMap<Integer, Set<Integer>>(); 	
	 	for(int j= 1;j<=n;j++){
	 		graph.put(j,  new HashSet<Integer>());
	 	}
	 	for(int j =0 ;j<m;j++){
	 		StringTokenizer st1 = new StringTokenizer(bf.readLine());
	 		int v1 = Integer.parseInt(st1.nextToken());
	 		int v2 = Integer.parseInt(st1.nextToken());
	 		graph.get(v1).add(v2);
	 		graph.get(v2).add(v1);
	 	}
	 	int max = 0;
	 	Set<Integer> seen = new HashSet<Integer>();
	 	for(int j = 1;j<=n;j++){
	 		
	 		if (!seen.contains(j)){
	 			
	 			Stack<Integer> dfs = new Stack<Integer>();
	 			dfs.add(j);
	 			Set<Integer> tempseen = new HashSet<Integer>();
	 			while(!dfs.isEmpty()){
	 				int vertex = dfs.pop();
	 				for(int child : graph.get(vertex)){
	 					if (!tempseen.contains(child))
	 						dfs.add(child);
	 				}
	 				tempseen.add(vertex);
	 				seen.add(vertex);
	 			}
	 			max = Math.max(max, tempseen.size());
	 		}
	 		
	 	}
	 	
	 	
 		out.println(max);
	 		
 		out.close();
 		
 		
 		
 	}
}
 	
 
//StringJoiner sj = new StringJoiner(" "); 
//sj.add(strings)
//sj.toString() gives string of those stuff w spaces or whatever that sequence is
//  [java]
import java.util.*;

public class Main{
  public static void main(String[] args){
    Scanner scan = new Scanner(System.in);
    int n = scan.nextInt();
    int m = scan.nextInt();
    ArrayList<HashSet<Integer>> a = new ArrayList<HashSet<Integer>>();
    boolean[] b = new boolean[n];

    for (int i=0;i<n;i++){
      HashSet<Integer> f = new HashSet<Integer>();
      a.add(f);
      b[i] = false;
    }

    for (int i=0;i<m;i++){
      int b1 = scan.nextInt();
      int c = scan.nextInt();
      HashSet<Integer> a1 = a.get(b1-1);
      a1.add(c);
      HashSet<Integer> a2 = a.get(c-1);
      a2.add(b1);
    }

    ArrayList<String> q = new ArrayList<String>();
    int max = 0;

    for (int i=0;i<n;i++){
      if (b[i] == false){
        int sum = 1;
        HashSet<Integer> check = a.get(i);
        b[i] = true;
        for (int kk : check){
          if (b[kk-1] == false){
              b[kk-1] = true;
              q.add(kk+"");
          }
        }

        while (q.size() > 0){
          sum += 1;
          int aa = Integer.parseInt(q.get(0));
          q.remove(0);
          HashSet<Integer> check1 = a.get(aa-1);
          for (int kkk : check1){
            if (b[kkk-1] == false){
                b[kkk-1] = true;
                q.add(kkk+"");
            }
          }
        }
        max = Math.max(max,sum);
      }
    }
    System.out.println(max);
  }
}
//  [cpp]
#include <bits/stdc++.h>
using namespace std;

int main() {
  int n,m;
  cin >> n >> m;
  vector<vector<int>> G(n);
  for(int i=0;i<m;i++){
    int a,b;
    bool al=false;
    cin >> a >> b;
    for(int x:G[a-1]){
      if(x==b-1) al=true;
    }
    if(!al){
      G[a-1].push_back(b-1);
      G[b-1].push_back(a-1);
    }
  } 
  int ans1=0,ans2=0;
  vector<bool> F(n,false);
  queue<int> bf;
  for(int i=0;i<n;i++){
    if(F[i]) continue;
    
    bf.push(i);
    F[i]=true;
    ans2=0;
    
    while(!bf.empty()){
      int k=bf.front();
      bf.pop();
      for(int x:G[k]){
        if(!F[x]) {
          bf.push(x);
          F[x]=true;
        }
      }
      ans2++;
    }
    
    ans1=max(ans1,ans2);
  }
  cout << ans1 << endl;     
  return 0;
}
//  [cpp]
#include<bits/stdc++.h>
using namespace std;
int n,m,sum=0;
bool vis[200005];
vector<int> fr[200005];
void dfs(int a)
{
    vis[a]=true;
    sum++;
    for(int i=0;i<fr[a].size();++i)
        if(!vis[fr[a][i]])
            dfs(fr[a][i]);
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<m;++i)
    {
        int x,y;
        cin>>x>>y;
        if(find(fr[x].begin(),fr[x].end(),y)==fr[x].end())
            fr[x].push_back(y);
        if(find(fr[y].begin(),fr[y].end(),x)==fr[y].end())
            fr[y].push_back(x);
    }
    for(int i=0;i<200005;++i)
            vis[i]=false;
    int ans=-1;
    for(int i=1;i<=n;++i)
        if(!vis[i])
            {
                dfs(i);
                ans=max(ans,sum);
                sum=0;
            }
    cout<<ans;
    return 0;
}
//  [cpp]
// 2020-08-29 21:10:06
// clang-format off
#include<bits/stdc++.h>
#ifdef LOCAL
#include "lib/debug.hpp"
#else
#define debug(...) 1
#endif
#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define rep(i, n) REP(i, 0, (n))
#define repc(i, n) REPC(i, 0, (n))
#define REP(i, n, m) for (int i = (int)(n); i < (int)(m); i++)
#define REPC(i, n, m) for (int i = (int)(n); i <= (int)(m); i++)
#define REPCM(i, n, m) for (int i = (int)(n); i >= (int)(m); i--)
using namespace std;
using ll = long long;
using ld = long double;
using pr = pair<ll, ll>;
using vll = vector<ll>;
using vpr = vector<pr>;
using P = pair<int, int>;
template<class T> inline bool chmin(T& a, const T& b) { if (a > b) { a = b; return true; } else return false; }
template<class T> inline bool chmax(T& a, const T& b) { if (a < b) { a = b; return true; } else return false; }
struct DisjointSet {
  std::map<int, int> parent, rank, num;

  void makeSet(int x) {
    parent[x] = x;
    rank[x] = 0;
    num[x] = 1;
  }

  bool same(int x, int y) {
    return findSet(x) == findSet(y);
  }

  void unite(int x, int y) {
    link(findSet(x), findSet(y));
  }

  void link(int x, int y) {
    if(rank[x] < rank[y]) {
      parent[x] = y;
      num[y] += num[x];
    } else {
      parent[y] = x;
      num[x] += num[y];
      if(rank[x] == rank[y]) rank[x]++;
    }
  }

  int numberOf(int x) {
    return num[findSet(x)];
  }

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

// clang-format on
void answer() {
  int n, m;
  cin >> n >> m;
  DisjointSet ds;
  rep(i, n) ds.makeSet(i);
  rep(i, m) {
    int a, b;
    cin >> a >> b;
    a--;
    b--;
    if (!ds.same(a, b)) ds.unite(a, b);
  }
  int ans = 0;
  rep(i, n) chmax(ans, ds.numberOf(i));
  cout << ans << '\n';
}
int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(0);
  answer();
  return 0;
}
//  [c]
#include <stdio.h>
#include <stdlib.h>

long *tree[200010];

int main(void) {

  long n,m,a,b;
  scanf("%ld %ld", &n, &m);
  long tree_s[n+1];
  for (long i = 1; i <= n; i++) {
    tree_s[i] = 0;
  }
  for (long i = 0; i < m; i++) {
    scanf("%ld %ld", &a, &b);
    tree[a] = realloc(tree[a], sizeof(long)*(tree_s[a]+1));
    tree[a][tree_s[a]] = b;
    tree_s[a]++;
    tree[b] = realloc(tree[b], sizeof(long)*(tree_s[b]+1));
    tree[b][tree_s[b]] = a;
    tree_s[b]++;
  }
  long visited[n+1],queue[n];
  visited[1] = 1;
  for (long i = 2; i <= n; i++) {
    visited[i] = 0;
  }
  queue[0] = 1;
  long head = 1,tail = 0,start = 0, end = 0,cur,next,count = 1,max = 0;
  int flag;
  while (1) {
    flag = 0;
    for (long i = start; i <= end; i++) {
      cur = queue[i];
      for (long j = 0; j < tree_s[cur]; j++) {
        next = tree[cur][j];
        if (visited[next] == 1) {
          continue;
        }
        visited[next] = 1;
        tail++;
        queue[tail] = next;
        count++;
        flag = 1;
      }
    }
    if (flag == 1) {
      start = end+1;
      end = tail;
    } else {
      if (count > max) {
        max = count;
      }
      if (end == n-1) {
        break;
      }
      count = 1;
      for (long i = head+1; i <= n; i++) {
        if (visited[i] == 0) {
          visited[i] = 1;
          tail++;
          queue[tail] = i;
          head = i;
          break;
        }
      }
      start = end+1;
      end = start;
    }
  }
  printf("%ld\n", max);

  return 0;
}
//  [javascript]
let inputString = "";
let currentLine = 0;
process.stdin.on("data", (data) => {
  inputString += data;
});
process.stdin.on("end", function () {
  inputString = inputString
    .trim()
    .split("\n")
    .map((str) => str.trim());
  main();
});
function readLine() {
  return inputString[currentLine++];
}
function main() {
  let [totalPeople, t] = readLine()
    .split(" ")
    .map((n) => parseInt(n));
  const graph = {};
  const seenCouple = {};
  while (t--) {
    let [p1, p2] = readLine()
      .split(" ")
      .map((n) => parseInt(n));

    if (!seenCouple[`${p1}-${p2}`]) {
      seenCouple[`${p1}-${p2}`] = true;

      if (!graph[p1]) graph[p1] = { [p2]: true };
      else graph[p1][p2] = true;
      if (!graph[p2]) graph[p2] = { [p1]: true };
      else graph[p2][p1] = true;
    }
  }

  let max = 1;
  let visited = {};
  for (let key in graph) {
    if (!visited[key]) {
      const stack = [key];
      let count = 0;
      while (stack.length) {
        const node = stack.pop();
        visited[node] = true;
        count++;
        for (let key in graph[node]) {
          if (!visited[key]) {
            visited[key] = true;
            stack.push(key);
          }
        }
      }
      max = Math.max(max, count);
    }
  }
  console.log(max);
}
//  [javascript]
const processData = (lines) => {
    const [n, m] = lines[0].split(' ').map( x => +x)
    let friendships = {}
    for (let i=0; i<m; i++) {
        const f = lines[i+1].split(' ').map(x => +x)
        if (!friendships[f[0]]) {
            friendships[f[0]] = {}
        }
        if (!friendships[f[1]]) {
            friendships[f[1]] = {}
        }
        friendships[f[0]][f[1]] = true
        friendships[f[1]][f[0]] = true
    }

    let maxCount = 1
    let visited = new Set()
    for (let p in friendships) {
        if (!visited.has(p)) {
            let count = 0
            let stack = [p]
            let cur = 0
            while (cur < stack.length) {
                count++
                let item = stack[cur]
                visited.add(item)
                cur++
                for (let p in friendships[item]) {
                    if (!visited.has(p)) {
                        visited.add(p)
                        stack.push(p)
                    }
                }
            }
            maxCount = Math.max(maxCount, count)
        }
    }

    console.log(maxCount)
}

let i = ''
process.stdin.on('data', c => i += c)
process.stdin.on('end', () => {
    const {EOL} = require('os')
    const lines = i.split(EOL) /*your input text, split by lines*/
    processData(lines)
})
//  [javascript]
console.log((args=>{
  const [[N,M],...friend] = args.trim().split`\n`.map(r=>r.split` `.map(v=>v|0));
  const G = Array.from({length:N},_=>[]);
  for ( const [A,B] of friend ) {
    G[A-1].push(B-1);
    G[B-1].push(A-1);
  }
  const g = Array(N).fill(0);
  let n = 1;
  for ( let i = 0; i < N; i++ ) {
    if ( g[i] ) continue;
    let stack = [i], m = 0;
    while( stack.length ) {
      const p = stack.pop();
      if ( !g[p] ) {
        g[p] = i+1;
        m++;
        for ( const next of G[p] ) if ( !g[next] ) {
          stack.push(next);
        }
      }
    }
    if (m > n) n = m;
  }
  return n;
})(require('fs').readFileSync('/dev/stdin','utf8')));
//  [go]
package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

var sc = bufio.NewScanner(os.Stdin)

func next() string {
	sc.Scan()
	return sc.Text()
}

func nextInt() int {
	a, _ := strconv.Atoi(next())
	return a
}

func first(m map[int]struct{}) int {
	for k, _ := range m {
		return k
	}

	return 0
}

func main() {
	buf := make([]byte, 1024*1024)
	sc.Buffer(buf, bufio.MaxScanTokenSize)
	sc.Split(bufio.ScanWords)

	n := nextInt()
	m := nextInt()

	v := make(map[int]map[int]struct{})

	for i := 0; i < m; i++ {
		a := nextInt()
		b := nextInt()

		if len(v[a]) == 0 {
			v[a] = make(map[int]struct{})
		}
		v[a][b] = struct{}{}

		if len(v[b]) == 0 {
			v[b] = make(map[int]struct{})
		}
		v[b][a] = struct{}{}
	}

	unvisited := make(map[int]struct{})

	for i := 1; i <= n; i++ {
		unvisited[i] = struct{}{}
	}

	maxGroupSize := 0
	for len(unvisited) > 0 {
		groupSize := 0
		startNode := first(unvisited)
		q := []int{startNode}

		delete(unvisited, startNode)

		for len(q) > 0 {
			node := q[0]
			q = q[1:]
			groupSize++

			if _, ok := v[node]; !ok {
				// no edge
				continue
			}

			for nextNode, _ := range v[node] {
				if _, ok := unvisited[nextNode]; ok {
					q = append(q, nextNode)
					delete(unvisited, nextNode)
				}
			}
		}

		if groupSize > maxGroupSize {
			maxGroupSize = groupSize
		}
	}

	fmt.Println(maxGroupSize)
}
//  [go]
package main

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"os"
	"strconv"
)

var mat []map[int]bool
var visited []bool

func dfs(a, cnt int) int {
	if visited[a] {
		return cnt
	}
	visited[a] = true
	cnt++

	for b := range mat[a] {
		cnt = dfs(b, cnt)
	}

	return cnt
}

func main() {
	n, m := readInt(), readInt()
	mat = make([]map[int]bool, n)
	for i := 0; i < m; i++ {
		a, b := readInt()-1, readInt()-1
		if mat[a] == nil {
			mat[a] = make(map[int]bool)
		}
		if mat[b] == nil {
			mat[b] = make(map[int]bool)
		}
		mat[a][b] = true
		mat[b][a] = true
	}

	ans := 0
	visited = make([]bool, n)
	for i := 0; i < n; i++ {
		if visited[i] {
			continue
		}
		ans = max(ans, dfs(i, 0))
	}

	fmt.Println(ans)
}

var (
	readString func() string
	readBytes  func() []byte
)

func init() {
	log.SetFlags(log.Lshortfile)
	readString, readBytes = newReadString(os.Stdin)
}

func newReadString(ior io.Reader) (func() string, func() []byte) {
	r := bufio.NewScanner(ior)
	r.Buffer(make([]byte, 1024), int(1e+11))
	r.Split(bufio.ScanWords)

	f1 := func() string {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Text()
	}
	f2 := func() []byte {
		if !r.Scan() {
			panic("Scan failed")
		}
		return r.Bytes()
	}
	return f1, f2
}

func readInt64() int64 {
	i, err := strconv.ParseInt(readString(), 10, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

func readInt() int {
	return int(readInt64())
}

func readFloat64() float64 {
	f, err := strconv.ParseFloat(readString(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func abs(a int) int {
	if a < 0 {
		return -a
	}
	return a
}

func sum(a []int) int {
	var ret int
	for i := range a {
		ret += a[i]
	}
	return ret
}

func sumFloat64(a []float64) float64 {
	var ret float64
	for i := range a {
		ret += a[i]
	}
	return ret
}

func gcd(m, n int) int {
	for m%n != 0 {
		m, n = n, m%n
	}
	return n
}

func lcm(m, n int) int {
	return m / gcd(m, n) * n
}
//  [ruby]
require 'pp'
require 'set'

n, m = gets.split.map(&:to_i)
x = []
path = {}
m.times do |i|
    a, b = gets.split.map(&:to_i)
    x << [a, b]
    path[a] ||= []
    path[a] << b
    path[b] ||= []
    path[b] << a
end

#spp path

if m == 0
    puts 1
    exit 0
end

visited = Array.new(n + 1, -1)
num = 0
i = 0

while path.empty?.!
    a, b = path.first
    path.delete(a)
    visited[a] = num

    stack = []
    b.each do |t|
        stack.push([t, num])
    end

    ##pp path
    #pp stack
    while stack.empty?.!
        k, num = stack.shift
        visited[k] = num
        nex = path.delete(k)
        if nex
            nex.each do |i|
                if visited[i] == -1
                    stack.push([i, num])
                end
            end
        end
    end

    num += 1
end

#pp visited
ans = visited.tally
ans.delete(-1)
puts ans.values.max
//  [ruby]
N,M,*P = $<.read.split.map &:to_i
A = [[]]*(N+1)
m = 1
M.times {|i|
  r,a = [],P[i+i,2]
  x,y = a.map {|i;j| (r<< i; i=j) while (j=A[i])[0]; r<< i; i}.sort
  g,h = [A[x],A[y]].map{|h| h.empty? ? a.to_h{[_1,0]} : h}.sort_by{_1.size}
  h.merge! g  if h.object_id != g.object_id
  r.each {A[_1] = y}
  A[y] = h
  m < h.size && m = h.size
}
p m
//  [ruby]
N,M,*P = $<.read.split.map &:to_i
C = [1]*(N+1)
A = C.map {[]}
P.each_slice(2).map{|s| a,b = s; a<b ? s : [b,a]}.sort!.each{|a,b| A[a] << b}
1.upto(N) {|i|
  j = (a=A[i]).map{A[_1][-1] || _1}.max
  next  unless j &.> i
  a.each {b=A[_1]; b << j  if b[-1]!=j}
  C[j] += C[i]
}
p C.max
//  [rust]
use proconio::{input};

#[derive(Debug, Clone)]
struct UnionFind {
    vec: Vec<Node>
}

#[derive(Debug, Copy, Clone)]
enum Node {
    Root(u32),
    Vertex(usize),
}

impl UnionFind {
    #[allow(dead_code)]
    fn new(n: usize) -> Self {
        UnionFind{
            vec: vec![Node::Root(1); n]
        }
    }

    #[allow(dead_code)]
    fn root(&self, x: usize) -> usize {
        match self.vec[x] {
            Node::Root(_) => x,
            Node::Vertex(parent) => self.root(parent),
        }
    }

    #[allow(dead_code)]
    fn root_update(&mut self, x: usize) -> usize {
        match self.vec[x] {
            Node::Root(_) => x,
            Node::Vertex(parent) => {
                let root = self.root(parent);
                self.vec[x] = Node::Vertex(root);
                root
            },
        }
    }

    #[allow(dead_code)]
    fn unite(&mut self, x: usize, y: usize) -> u32 {
        let (rx, ry) = (self.root_update(x), self.root_update(y));
        if rx == ry {
            return 0;
        }
        if let (Node::Root(x_root_size), Node::Root(y_root_size)) = (self.vec[rx], self.vec[ry]) {
            if x_root_size > y_root_size {
                self.vec[ry] = Node::Root(x_root_size + y_root_size);
                self.vec[rx] = Node::Vertex(ry);
            } else {
                self.vec[rx] = Node::Root(x_root_size + y_root_size);
                self.vec[ry] = Node::Vertex(rx); 
            }
            return x_root_size + y_root_size;
        } else {
            unreachable!();
        }
    }

    #[allow(dead_code)]
    fn size(&self, x: usize) -> u32 {
        if let Node::Root(s) = self.vec[self.root(x)] {
            return s;
        } else {
            unreachable!();
        }
    }

    #[allow(dead_code)]
    fn max_size(&self) -> u32 {
        let mut answer = 0;
        for i in &self.vec {
            match i {
                Node::Root(size) => {
                    if answer < *size {
                        answer = *size;
                    }
                },
                _ => {},
            }
        }
        return answer;

    }
}
 
fn main() {
    input! {
        n: usize,
        m: usize,
        t: [(usize, usize); m],
    }
 
    let mut uf = UnionFind::new(n);
 
    let mut answer = 1;
    for (a, b) in t {
        let root_size = uf.unite(a-1, b-1);
        if root_size > answer {
            answer = root_size;
        }
    }
    
    println!("{}", answer);
}
//  [rust]
use proconio::input;
use proconio::marker::Usize1;
use std::collections::HashSet;

fn dfs(
  seen: &mut HashSet<usize>,
  frends: &mut HashSet<usize>,
  map: &Vec<Vec<usize>>,
  from: usize
) {
  if seen.contains(&from) { return }
  seen.insert(from);
  frends.insert(from);
  
  for to in map[from].iter() {
    dfs(seen, frends, map, *to);
  }
}

fn main() {
  input! {
    n: usize,
    m: usize,
    pairs: [(Usize1,Usize1);m]
  }
  
  let mut map: Vec<Vec<usize>> = vec![vec![];n];
  let mut seen: HashSet<usize> = HashSet::new();
  for (from, to) in pairs {
    map[from].push(to);
    map[to].push(from);
  }
  let mut max = 0;
  
  for from in 0..n {
    let mut frends = HashSet::new();
    seen.insert(from);
    frends.insert(from);
    for to in map[from].iter() {
      dfs(&mut seen, &mut frends, &map, *to);
    }
    
    max = std::cmp::max(max, frends.len());
  }
  
  println!("{}", max);
}
//  [swift]
let NM = readLine()!.split(separator: " ").compactMap { Int($0) }
let m = NM[1]

let ABM = (0..<m).map { _ in readLine()!.split(separator: " ").compactMap { Int($0) } }

var arrayDic = [Int: Int]()
var circle = [[Int]]()
for i in 0..<m {
    let ai = ABM[i][0]
    let bi = ABM[i][1]
    if arrayDic[ai] == nil && arrayDic[bi] == nil {
        circle.append([ai, bi])
        arrayDic[ai] = circle.count-1
        arrayDic[bi] = circle.count-1
    } else if let index = arrayDic[ai], arrayDic[bi] == nil {
        circle[index].append(bi)
        arrayDic[bi] = index
    } else if let index = arrayDic[bi], arrayDic[ai] == nil {
        circle[index].append(ai)
        arrayDic[ai] = index
    } else if let aIndex = arrayDic[ai], let bIndex = arrayDic[bi] {
        if aIndex == bIndex { continue }

        let maxIndex = circle[aIndex].count > circle[bIndex].count ? aIndex : bIndex
        let minIndex = circle[aIndex].count > circle[bIndex].count ? bIndex : aIndex

        for element in circle[minIndex] {
            arrayDic[element] = maxIndex
        }
        circle[maxIndex].append(contentsOf: circle[minIndex])
    }
}

let result = circle.reduce(0, { max($0, $1.count) })
print(result > 0 ? result : 1)
//  [swift]
final class UnionFindTree2 {
    
    private enum Parent {
        case element(Int)
        case root(groupSize: Int)
    }
    
    private var parents: [Parent]
    
    init(size: Int) {
        self.parents = [Parent](repeating: .root(groupSize: 1), count: size)
    }
    
    func group(of element: Int) -> (representative: Int, size: Int) {
        let parentOfElement = parents[element]
        switch parentOfElement {
        case .element(let parent):
            let (representative, groupSize) = group(of: parent)
            self.parents[element] = .element(representative)
            return (representative: representative, size: groupSize)
        case .root(let groupSize):
            return (representative: element, size: groupSize)
        }
    }
    
    func sameGroupContains(_ a: Int, and b: Int) -> Bool {
        group(of: a) == group(of: b)
    }
    
    func uniteGroups(of a: Int, and b: Int) {
        var smallerGroup = group(of: a)
        var biggerGroup = group(of: b)
        guard smallerGroup.representative != biggerGroup.representative else { return }
        if smallerGroup.size > biggerGroup.size {
            swap(&smallerGroup, &biggerGroup)
        }
        self.parents[biggerGroup.representative] = .root(groupSize: smallerGroup.size + biggerGroup.size)
        self.parents[smallerGroup.representative] = .element(biggerGroup.representative)
    }
}

func main(input1: String = readLine()!) {
    let integers = input1.split(separator: " ").map { Int($0)! }
    let n = integers[0]
    let m = integers[1]
    
    let tree = UnionFindTree2(size: n)
    for _ in 0..<m {
        let integers = readLine()!.split(separator: " ").map { Int($0)! }
        let a = integers[0] - 1
        let b = integers[1] - 1
        tree.uniteGroups(of: a, and: b)
    }
    var maxGroupSize = 0
    for someone in 0..<n {
        let groupSize = tree.group(of: someone).size
        if maxGroupSize < groupSize {
            maxGroupSize = groupSize
        }
    }
    print(maxGroupSize)
}

main()
//  [typescript]
import * as fs from 'fs';

const input = fs.readFileSync('/dev/stdin', 'utf8');
// const input = fs.readFileSync('./input.txt', 'utf8');

_d(input);

function _d(input: string) {
  const [_NM, ..._AB] = input.split('\n');
  _AB.pop(); // empty line

  const [N, M] = _NM.split(' ').map((s) => parseInt(s));
  const AB = _AB.map(
    (s) => s.split(' ').map((s) => parseInt(s)) as [number, number]
  );

  const directFriends: Set<number>[] = Array.from({ length: N }).map(
    () => new Set<number>()
  ); // a-1 と直接友達な人の添え字 [...b-1]
  for (let i = 0; i < AB.length; i++) {
    const [Ai, Bi] = AB[i];
    directFriends[Ai - 1].add(Bi - 1);
    directFriends[Bi - 1].add(Ai - 1);
  }

  let maxFriendsNum = 0; // 最も大きな「友達関係」の人数
  const searched = new Set<number>(); // 探索済みフラグ

  for (let i = 0; i < N; i++) {
    if (searched.has(i)) continue; // 計算済み（過去に計算された友達関係の中に含まれていた）

    // 友達の数を数える
    const friends = new Set([i]); // 発見された全ての友達の添え字セット
    const pool = [i]; // 探索すべき添え字のリスト

    // 再帰的に探索スタート
    while (pool.length > 0) {
      const target = pool.pop();
      if (target === undefined) continue; // type hint

      if (searched.has(target)) continue; // 探索ずみ
      searched.add(target); // 探索済みをチェックする

      for (const j of Array.from(directFriends[target])) {
        friends.add(j); // 友達に追加
        if (!searched.has(j)) {
          pool.push(j); // 友達の友達をさらに追跡
        }
      }
    }

    maxFriendsNum = Math.max(maxFriendsNum, friends.size); // 最大値を更新
    if (maxFriendsNum >= N / 2) {
      break; // 半数以上の友達関係を見つけた
    }
  }

  console.log(maxFriendsNum); // 最も大きな「友達関係」の人数が、少なくとも必要なグループの数になる
}
//  [typescript]
import * as fs from 'fs';

class UnionFind {
  list: number[];
  sizeList: number[];
  constructor(N: number) {
    this.list = new Array(N).fill(-1);
    this.sizeList = new Array(N).fill(1);
  }

  root(i: number): number {
    if (this.list[i] === -1) {
      return i;
    }
    return this.root(this.list[i]);
  }

  unite(i: number, j: number): boolean {
    let rootI = this.root(i);
    let rootJ = this.root(j);
    if (rootI === rootJ) {
      return false;
    }
    if (rootI > rootJ) {
      let tmp = rootI;
      rootI = rootJ;
      rootJ = tmp;
    }
    this.sizeList[rootI] += this.sizeList[rootJ];
    this.list[rootJ] = rootI;
    return true;
  }

  size(i: number): number {
    return this.sizeList[this.root(i)];
  }
}

function main(input): void {
  input = input.split('\n');
  const [N, M] = input[0].split(' ').map(i => parseInt(i));
  let ABList = input.splice(1).map(l => l.split(' ').map(i => parseInt(i))).splice(0, M);

  const u = new UnionFind(N);
  for (let idx in ABList) {
    u.unite(ABList[idx][0] - 1, ABList[idx][1] - 1);
  }

  let ans = u.sizeList.reduce((prev, current) => prev > current ? prev : current);
  console.log('%s', ans);
}

main(fs.readFileSync('/dev/stdin', 'utf8'));
//  [typescript]
// @ts-ignore
import * as fs from 'fs';

// メイン
function main(input: string[]) {
    var work0: number[] = input.shift().split(" ").map(x => Number(x));
    var n: number = work0[0];
    var m: number = work0[1];
    var node: number[][] = input.map(x => x.split(" ").map(x => Number(x) - 1));
    g_uf_root = new Array(n).fill(-1);
    g_uf_count = new Array(n).fill(1);
    node.forEach(value => {
        var a: number = value[0];
        var b: number = value[1];
        UF_mergeRoot(a, b);
    });
    console.log(Math_max(g_uf_count));
}

// math
function Math_max(arr: number[]) {
    return arr.reduce(function (x, y) {
        return Math.max(x, y);
    });
}

// union-find
var g_uf_root: number[];
var g_uf_count: number[];
function UF_getRoot(index: number) {
    if (g_uf_root[index] < 0) {
        return index;
    } else {
        var work0: number = UF_getRoot(g_uf_root[index]);
        g_uf_root[index] = work0;
        return work0
    }
}
function UF_mergeRoot(a: number, b: number) {
    var root0: number = UF_getRoot(a);
    var root1: number = UF_getRoot(b);
if (root0 == root1) return;
    if (root0 > root1) [root0, root1] = [root1, root0];
    g_uf_count[root0] += g_uf_count[root1];
    g_uf_count[root1] = 0;
    g_uf_root[root1] = root0;
}

// エントリポイント
// - OSによるパラメタの処理の違いを吸収
function entrypoint() {
    try {
        var input = fs.readFileSync("/dev/stdin", "utf8").trim().split("\n");
        console.debug = function () { };
        main(input);
    }
    catch (ex) {
        console.log("----");
        console.log("file='%s'", __filename.split("\\").slice(-1)[0]);
        console.log("----");
        const lines: string[] = [];
        // @ts-ignore
        const reader = require('readline').createInterface({
            // @ts-ignore
            input: process.stdin,
            // @ts-ignore
            output: process.stdout
        });
        reader.on('line', function (line: string) {
            lines.push(line);
        });
        reader.on('close', function () {
            input = lines;
            console.log("input=%o", input);
            console.time();
            console.log("----")
            main(input);
            console.log("----")
            console.timeEnd();
        });
    }
}
entrypoint();
//  [python]
import sys
from collections import deque, Counter, defaultdict
from fractions import gcd
input = sys.stdin.readline

def eprint(s):
    if type(s) != type('str'):
        s=str(s)

    sys.stderr.write(s+'\n')
    return

def expected_value(n):
    ans = 0

    for i in range(1, n+1):
        ans += i/n

    # eprint(ans)
    return ans

def main():
    n, k = map(int, input().split())
    Ps = list(map(int, input().split()))
    
    Cs = [0]*n
    for i in range(n):
        if i == 0:
            Cs[i] = Ps[i]
        else:
            Cs[i] = Cs[i-1] + Ps[i]
    
    Ds = list()
    mi = -10**9
    mix = 0
    for i in range(n-k+1):
        if i == 0:
            Ds.append(Cs[i+k-1])
        else:
            Ds.append(Cs[i+k-1] - Cs[i-1])

        if Ds[i] > mi:
            mi = Ds[i]
            mix = i

    
    #mix ~ mix+kまでの
    v = int()
    for i in range(k):
        v += expected_value(Ps[mix+i])
        
    print(v)

    return

if __name__ == '__main__':
    main()
//  [python]
import numpy
N, K = map(int, input().split())
p = numpy.array(list(map(int, input().split())))
P = []
nowsum = 0
for p1 in p:
    nowsum += p1
    P.append(nowsum)

max = 0
nowsum = 0
for i in range(N-K+1):
    if i == 0:
        temp = P[K-1]
    else:
        temp = P[i+K-1]-P[i-1]
    if max < temp:
        max = temp
        maxno = i
exsum = 0
for i in range(K):
    temp = p[i+maxno]
    exsum += (0.5*temp*(temp+1))/temp
print(exsum)
//  [python]
import numpy
N, K = map(int, input().split())
P = [int(i) for i in input().split()]
P = [0]+list(map(lambda x: (x+1)/2, P))

S = numpy.cumsum(P)

ans = 0
for i in range(K, N+1):
    ans = max(ans, S[i]-S[i-K])
print(ans)
//  [java]
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;

public class Main {

		static int[] mx = {1, 0, -1, 0};
		static int[] my = {1, 0, -1, 0};
		static int h;
		static int w;
		static char[][] map;

		public static void main(String[] args) {
			Scanner scanner = new Scanner(System.in);

			String[] temp = scanner.nextLine().split(" ");
			int n  = Integer.parseInt(temp[0]);
			int m  = Integer.parseInt(temp[1]);

			String[] t = scanner.nextLine().split(" ");
			int[] sum  = new int[n];
			int[] lst  = new int[n];

			lst[0] = Integer.parseInt(t[0]);
			sum[0] = lst[0];
			for(int i = 1; i < n; i++) {

				lst[i] = Integer.parseInt(t[i]);
				sum[i] = lst[i] + sum[i - 1];
			}

			int max = 0;
			int num = 0;
			for(int i = 0; i < n - m; i++) {

				int te = sum[i + m] - sum[i];
				if(max < te) {
					max = te;
					num = i + 1;
				}
			}


			double ans = 0;

			for(int i = num; i < num + m; i ++) {

				for(int j = 1; j <= lst[i]; j++) {

					ans += ((double)j) / lst[i];
				}
			}

			System.out.println(ans);
		}
	}
//  [cpp]
#include <iostream>
#include <cmath>
#include <stdint.h>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <set>
using namespace std;
 
#define int long long
#define INF (1e18)+1
 
int nChoosek( int n, int k )
{
    if (k > n) return 0;
    if (k * 2 > n) k = n-k;
    if (k == 0) return 1;

    int result = n;
    for( int i = 2; i <= k; ++i ) {
        result *= (n-i+1);
        result /= i; 
    }
    return result;
}

int choose2(int n){
	
	return n*(n-1)/2;
}


double expectedValue(int value){
	double sum = 0;
	double div = 1.0 / value;
	for(int i=1; i<=value; i++){	
		sum = sum + (i*div);
	}
	return sum;
}
 int arr[200001];
int32_t main() {
 
   int N,K;
   
   cin >> N >>K ;
   
   for(int i=0; i<N; i++){
   	
   		cin >> arr[i];
   	
   }
   
    int maxi = 0;
    int index = 0;
   for(int i=0; i<N; i++){
   		int sum = 0;
   		if(i+K > N){
   			break;
		}
   		for(int j=0; j<K; j++){
   			
		   	sum+= arr[i+j];
   			
		}
   		if(sum > maxi){
   			maxi = sum;
   			index = i;
		}
   } 
  // cout << index << endl;
    double ans = 0;
 	for(int i = 0; i < K; i++){
 		
 		ans += expectedValue(arr[i+index]);
 		
	 }
 	cout << fixed << setprecision(12) <<  ans << endl;
}
//  [cpp]
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <fstream>
#include <string>
#include <math.h>
#include <cstdlib>
#include <istream>
#include <sstream>
#include <cctype>
#include <iomanip>
//cout << fixed << setprecision(20) << *** << endl;
#define rep(i,N) for(int i=0;i<(int)N;++i)
typedef long long ll;
using namespace std;

double kitaichi(ll N){
	double d=0,t;
	for(ll i=1;i<=N;i++){
		t=i/(double)N;
		d=d+t;
	}
	return d;
}

int main()
{
	ll N,K,t;
	double ANS=0;
	vector<ll>Dice;
	vector<pair<ll,ll>>V;
	cin>>N>>K;
	rep(i,N){
		cin>>t;
		Dice.push_back(t);
	}
	rep(i,N-K+1){
		ll t=0;
		rep(j,K){
			t=t+Dice[i+j];
		}
		V.push_back(make_pair(t,i));
	}
	sort(V.begin(),V.end());
	rep(i,K){
		ANS=ANS+kitaichi(Dice[V.back().second+i]);
	}
	cout << fixed << setprecision(20) << ANS << endl;
}
//  [cpp]
#include <iostream>
#include <vector>
#include <numeric>
#include <iomanip>

using namespace std;

int main(int argc, char const *argv[])
{
    int N, K;
    cin >> N >> K;
    vector<int> p;
    int in;
    for (int i = 0; i < N; i++)
    {
        cin >> in;
        p.emplace_back(in);
    }

    int sum;
    int max = 0;
    int maxi;
    vector<int>::iterator pstart, pend;
    for (int i = 0; i <= N - K; i++)
    {
        pstart = p.begin() + i;
        pend = pstart + K;
        sum = accumulate(pstart, pend, 0);
        if (sum > max)
        {
            max = sum;
            maxi = i;
        }

    }

    double ans = 0.0;
    for (int i = 0; i < K; i++)
    {
        ans += 0.5 * (1 + p[maxi + i]);
    }
    
    cout <<  fixed  <<  setprecision(12)  <<  ans  << endl;
    
    return 0;
}
//  [c]
#include <stdio.h>
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define max(a, b) ((a) > (b) ? (a) : (b))

int main(void)
{
    int n, k, p[200001];
    double ans = 0;
    double e[200001] = {0}, tmp[2] = {0};
    scanf("%d%d", &n, &k);
    rep(i, n)
        scanf("%d", &p[i]);

    rep(i, n) for (int j = 1; j <= p[i]; j++)
        e[i] += (double)j / (double)p[i];

    rep(i, k)
        ans += e[i];

    tmp[0] = ans;
    rep(i, n - k)
    {
        tmp[1] = tmp[0] - e[i] + e[i + k];
        ans = max(ans, tmp[1]);
        tmp[0] = tmp[1];
    }

    printf("%.12f\n", ans);
    return 0;
}
//  [c]
#include <stdio.h>
double mean(double n)
{
	double sum=0;
	for(int i=1;i<=n;i++)
	{
		sum+=i;
	}
	return sum/n;
}
int main()
{
	double n,k;
	scanf("%lf %lf",&n,&k);
	double arr[200005];
	for(int i=1;i<=n;i++)
	{
		scanf("%lf",&arr[i]);
	}
	int l=1;
	int r=k;
	double sum=0;
	for(int i=1;i<=k;i++)
	{
		sum+=mean(arr[i]);
	}
	double max=sum;
	while(r!=n)
	{
		r++;
		sum=sum-mean(arr[l])+mean(arr[r]);
		l++;
		if(sum>max)
		max=sum;
	}
	printf("%lf",max);
	return 0;
}
//  [c]
#include <stdio.h>

double qidaizhi(int a){
    double sum=0;
    for(int i=1;i<=a;i++){
        sum+=i;
    }
    return sum/a;
}

int main()
{
    int N,K;
    double max,sum=0;
    scanf("%d%d",&N,&K);
    int p[N];
    for(int i=0;i<N;i++){
        scanf("%d",&p[i]);
    }

    int head=K-1,tail=0;
    for(int i=0;i<K;i++){
        sum+=qidaizhi(p[i]);
    }
    max=sum;

    while(head!=N-1){
        head++;
        sum=sum+qidaizhi(p[head])-qidaizhi(p[tail]);
        tail++;
        if(sum>max) max=sum;
    }

    printf("%f",max);

    return 0;
}
//  [javascript]
var input = require("fs").readFileSync("/dev/stdin", "utf8").trim().split("\n");
var obj = {
  "list" : input,
  "index" : 0,
  "max" : input.length,
  "next" : function(){
    if(!this.hasNext()){throw "NoSuchElementException:次に要素は無いよ";}
    var returnObj = this.list[this.index];
    this.index++;
    return returnObj;
  },
  "hasNext" : function(){return (this.index < this.max);}
}
Main();
function next(){return obj.next();}
function hasNext(){return obj.hasNext();}
function myout(t){console.log(t);}//standard output
function myerr(t){console.error(t);}//standard error
//[no]要素の扱い。数値型
//不明値、異常時:引数そのまま返す　1:数値へ変換
//2:半角SPで分割 4:半角SPで分割し、数値配列へ
//6:1文字で分割  7:1文字で分割し、数値配列へ
//8:半角SPで結合 9:改行で結合 0:文字なしで結合
function myconv(i,no){try{switch(no){case 1:return parseInt(i);case 2:return i.split(" ");case 4:return i.split(" ").map((a)=>Number(a));case 6:return i.split("");case 7:return i.split("").map((a)=>Number(a));case 8:return i.join(" ");case 9:return i.join("\n");case 0:return i.join("");default:return i;}}catch(e){return i;}}
function Main(){
  var one = myconv(next(),4);
  var N = one[0];
  var K = one[1];
  var list = myconv(next(),4);
  var set = new Array(1001);
  for(var i = 1; i <= 1000; i++){
    //種類がiの時の期待値を計算する
    var add = 0;
    for(var j = 1; j <= i; j++){
      add += j / i;
    }
    set[i] = add;
  }
  
  //リスト書き換え
  for(var i = 0; i < N; i++){
    list[i] = set[list[i]];
  }
  
  var max = 0;
  var tmp = 0;
  for(var i = 0; i < N; i++){
    if(i < K){
       max += list[i];
      tmp += list[i];
    }else{
       tmp = tmp - list[i - K] + list[i];
      max = Math.max(tmp,max);
    }
  }
  myout(max);
}
//  [javascript]
//Don't have to see. start------------------------------------------
var read = require('readline').createInterface({
  input: process.stdin, output: process.stdout
});
var obj; var inLine = [];
read.on('line', function(input){inLine.push(input);});
read.on('close', function(){
  obj = init(inLine);
  console.error('\n↑入力 ↓出力');
  Main();
});
function makeClone(obj){return (obj instanceof Set) ? new Set(Array.from(obj)) : JSON.parse(JSON.stringify(obj));}
function nextInt(){return myconv(next(),1);} function nextStrArray(){return myconv(next(),2);}
function nextIntArray(){return myconv(next(),4);} function nextCharArray(){return myconv(next(),6);}
function next(){return obj.next();} function hasNext(){return obj.hasNext();}
function init(input){  
  return {
    list : input, index : 0, max : input.length,
    hasNext : function(){return (this.index < this.max);},
    next : function(){if(this.hasNext()){return this.list[this.index++];}else{throw 'ArrayIndexOutOfBoundsException ‚There is no more input';}}
  };
}
function myout(s){console.log(s);}
function myerr(s){console.error('debug:' + require('util').inspect(s,false,null));}
//param "no" is
//unknown or outlier : return i. 1: parseInt.
//2: split space. 4: split space and parseInt.
//6: split 1 character. 7: split 1 character and parseInt.
//8: join space. 9: join nextline. 0: join no character.
function myconv(i,no){try{switch(no){case 1:return parseInt(i);case 2:return i.split(' ');case 4:return i.split(' ').map(Number);case 6:return i.split('');case 7:return i.split('').map(Number);case 8:return i.join(' ');case 9:return i.join('\n');case 0:return i.join('');default:return i;}}catch(e){return i;}}

//Don't have to see. end------------------------------------------
function Main(){
  var one = nextIntArray();
  var N = one[0];
  var K = one[1];
  var list = nextIntArray();
  for(var i = 0; i < N; i++){
    var sum = 0;
    for(var j = 1; j <= list[i]; j++){
      sum += j / list[i];
    }
    list[i] = sum;
  }
  var sum = 0;
  var max = 0;
  for(var i = 0; i < N; i++){
    if(i < K){
      sum += list[i];
      max = sum;
    }else{
      sum -= list[i - K];
      sum += list[i];
      max = Math.max(max, sum);
    }
  }
  myout(max);
}
//  [javascript]
'use strict'
const main = arg => {
	const input = arg.trim().split("\n");
	let K = input[0].split(' ')[1]
	let P = input[1].split(' ').map(p => Number(p))
	let sums = []
	let ruisekiwa = [P[0]]
	for(let i = 1; i < P.length ; i++) {
		ruisekiwa.push(ruisekiwa[i - 1] + P[i])
	}
	sums.push({v :ruisekiwa[K - 1], i: 0})
	for(let i = 0; i < P.length - K; i++) {
		sums.push({ v : ruisekiwa[i + Number(K)] - ruisekiwa[i], i: i + 1})
	}
	let dp = [0]
	for(let i = 1; i <= 1000 ; i++) {
		dp.push((dp[i - 1] + i))
	}
	sums = sums.sort((a, b) => a.v- b.v)
	let index = sums[sums.length - 1].i
	let tmp = P.slice(index, index + Number(K))
	let result = 0
	for(let i = 0; i < tmp.length ; i++) {
		result += dp[tmp[i]] / tmp[i]
	}
	console.log(result.toFixed( 12 ))
	
}   
main(require('fs').readFileSync('/dev/stdin', 'utf8'));
//  [go]
package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

var sc *bufio.Scanner

func init() {
	// 100MB
	bufsize := 100 * 1024 * 1024
	sc = bufio.NewScanner(os.Stdin)
	sc.Buffer(make([]byte, bufio.MaxScanTokenSize), bufsize)
	sc.Split(bufio.ScanWords)
}
func readInt() int              { return readIntArray(1)[0] }
func readInt2() (int, int)      { a := readIntArray(2); return a[0], a[1] }
func readInt3() (int, int, int) { a := readIntArray(3); return a[0], a[1], a[2] }
func readIntArray(n int) []int {
	s := readStringArray(n)
	a := make([]int, n)
	for i := range a {
		a[i], _ = strconv.Atoi(s[i])
	}
	return a
}
func readString() string            { return readStringArray(1)[0] }
func readString2() (string, string) { a := readStringArray(2); return a[0], a[1] }
func readStringArray(n int) []string {
	a := make([]string, n)
	for i := 0; i < n; i++ {
		sc.Scan()
		a[i] = sc.Text()
	}
	return a
}
func max(ns ...int) int {
	max := ns[0]
	for _, n := range ns {
		if n > max {
			max = n
		}
	}
	return max
}
func min(ns ...int) int {
	min := ns[0]
	for _, n := range ns {
		if n < min {
			min = n
		}
	}
	return min
}
func abs(x int) int {
	if x < 0 {
		return -x
	}
	return x
}

func main() {
	N, K := readInt2()
	P := readIntArray(N)

	head := P[0]
	var initial int
	for i := 0; i < K; i++ {
		initial += P[i]
	}
	//fmt.Printf("init: %d\n", initial)

	tmp := initial
	max := tmp
	var maxIdx int
	for i := 1; i <= N-K; i++ {
		tmp -= head
		tmp += P[i+K-1]
		head = P[i]
		//fmt.Printf("total[%d]: %d\n", i, tmp)
		if max < tmp {
			max = tmp
			maxIdx = i
		}
	}
	//fmt.Printf("max pair: %d-%d\n", maxIdx, maxIdx+K-1)

	var et float64
	for i := maxIdx; i <= maxIdx+K-1; i++ {
		et += expval(P[i])
	}
	fmt.Println(et)
}

func expval(p int) float64 {
	var e float64
	for i := 1; i <= p; i++ {
		e += float64(i) / float64(p)
	}
	//fmt.Printf("p: %d, e: %f\n", p, e)
	return e
}
//  [go]
package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

var sc = bufio.NewScanner(os.Stdin)

func nextFloat64() float64 {
	sc.Scan()
	f, _ := strconv.ParseFloat(sc.Text(), 64)
	return f
}

func nextInt() int {
	sc.Scan()
	i, _ := strconv.Atoi(sc.Text())
	return i
}

func expectedValue(x float64) float64 {
	var e float64
	for i := 1; i <= int(x); i++ {
		e += float64(i) / x
	}
	return e
}

func main() {
	sc.Split(bufio.ScanWords)
	n, k := nextInt(), nextInt()
	evs := make([]float64, n)
	for i := 0; i < n; i++ {
		p := nextFloat64()
		evs[i] = expectedValue(p)
	}

	// initialize
	var ev float64
	for i := 0; i < k; i++ {
		ev += evs[i]
	}

	maxEv := ev
	left := 0
	for i := k; i < n; i++ {
		ev = ev - evs[left] + evs[i]
		left++
		if ev > maxEv {
			maxEv = ev
		}
	}
	fmt.Printf("%0.7f\n", maxEv)
}
//  [go]
package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

var sc = bufio.NewScanner(os.Stdin)

func init() {
	sc.Split(bufio.ScanWords)
}

func nextInt() int {
	sc.Scan()
	i, e := strconv.Atoi(sc.Text())
	if e != nil {
		panic(e)
	}
	return i
}

func main() {
	n := nextInt()
	k := nextInt()

	p := make([]float64, n)
	for i := 0; i < n; i++ {
		p[i] = ex(nextInt())
	}

	s := make([]float64, n + 1)
	s[0] = 0
	for i := 1; i <= n; i++ {
		s[i] = s[i - 1] + p[i - 1]
	}

	max := float64(0)
	t := make([]float64, n - k + 1)
	for i := 0; i < n - k + 1; i++ {
		t[i] = s[i + k] - s[i]
		if max < t[i] {
			max = t[i]
		}
	}

	fmt.Printf("%.12f", max)
}

func ex(x int) float64 {
	total := float64(0)
	for i := 1; i <= x; i++ {
		total += float64(i) / float64(x)
	}
	return total
}
//  [ruby]
class BIT
  def initialize(n)
    @tree = Array.new(n + 1, 0)
  end

  def add(i, diff)
    while i < @tree.size
      @tree[i] += diff
      i += (i & -i)
    end
  end

  def sum(i)
    t = 0
    while i > 0 do
      t += @tree[i]
      i -= (i & -i)
    end
    return t
  end
end

n, k = gets.chomp.split.map(&:to_i)
ps = gets.chomp.split.map(&:to_i)
es = ps.map do |p|
  p * (p + 1) / 2.0 * (1.0 / p)
end

bit = BIT.new(n)
1.upto(n) do |i|
  bit.add(i, es[i - 1])
end

m = bit.sum(k)
k.upto(n) do |i|
  t = bit.sum(i) - bit.sum(i - k)
  m = [t, m].max
end

puts m
//  [ruby]
n, k = gets.chomp.split.map(&:to_i)
pn = gets.chomp.split.map(&:to_r)

sums = []*n
n.times do |i|
  sums[i] = (pn[i] + 1) / 2
end

sum = sums.take(k).inject(&:+)
head = 0
max = sum
(k...n).to_a.each do |i|
  max = [max, sum - sums[head] + sums[i]].max
  sum = sum - sums[head] + sums[i]
  head += 1
end
puts max.to_f
//  [ruby]
N, K = gets.chomp.split(' ').map(&:to_i)
P = gets.chomp.split(' ').map { |p_i| Rational((p_i.to_i * (p_i.to_i + 1) / 2), p_i.to_i) }

s = []
s[0] = Rational(0)
N.times do |i|
  s[i + 1] = P[i] + s[i]
end

e = []
(K..N).each do |i|
  e[i] = s[i] - s[i - K]
end
puts e.compact.max.to_f
//  [rust]
use std::io::*;
use std::str::FromStr;

fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

fn main() {
    let n = read();
    let k: i32 = read();
    let mut p_arr = vec![0; n];
    for i in 0..n {
        p_arr[i] = read();
    }
    let mut max = 0;
    let mut max_start = 0;
    let mut max_end = 0;
    for (i, _) in p_arr.iter().enumerate() {
        let before_i: i32 = if k - 2 < 0 { 0 } else { k - 2 };
        if i > before_i as usize {
            let mut sum = 0;
            let start = i - (k as usize - 1);
            let end = i + 1;
            for p in p_arr[start..end].iter() {
                sum += *p;
            }
            if max < sum {
                max = sum;
                max_start = i - (k as usize - 1);
                max_end = i + 1;
            }
        }
    }
    let mut res = 0.0;
    for p in p_arr[max_start..max_end].iter() {
        let mut sum = 0;
        for i in 1..*p + 1 {
            sum += i;
        }
        let expected = sum as f64 / *p as f64;
        res += expected;
    }
    if res == 0.0 {
        let p = p_arr[0];
        let mut sum = 0;
        for i in 1..p + 1 {
            sum += i;
        }
        let expected = sum as f64 / p as f64;
        println!("{}", expected);
    } else {
        println!("{}", res);
    }
}