import java.util.Arrays;
import java.util.Scanner;

public class Solution {

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

        int n = sc.nextInt(), m = sc.nextInt(), w = sc.nextInt();

        int[] a = new int[n];

        for (int i = 0; i < n; i++) {
            a[i] = sc.nextInt();
        }

        int lo = 0, hi = 100000, max = 0;

        while (lo <= hi) {
            int mid = lo + (hi - lo) / 2;
            if (check(a, mid, n, m, w)) {
                max = mid;
                lo = mid + 1;
            } else hi = mid - 1;
        }
        System.out.println(max);
    }

    public static boolean check(int[] original, int target, int n, int m, int w) {
        int[] a = Arrays.copyOf(original, original.length);
        int i;
        for (i = 0; i < a.length && m > 0; i++) {
            if (a[i] < target) {
                while (a[i] < target && m > 0) {
                    for (int j = 0; j < w && (i + j) < a.length; j++) {
                        a[i + j] = a[i + j] + 1;
                    }
                    m--;
                }
            }
        }
        for (i = i-1; i < a.length; i++) {
            if (a[i] < target) return false;
        }
        return true;
    }
}


import java.util.Scanner;

public class Solution {

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

        int n = sc.nextInt(), m = sc.nextInt(), w = sc.nextInt();

        int[] a = new int[n];
        int[] b = new int[n];

        for (int i = 0; i < n; i++) {
            a[i] = sc.nextInt();
        }

        int lo = 0, hi = 1000100000, max = 0;

        while (lo <= hi) {
            int mid = lo + (hi - lo) / 2;
            if (check(a, b,mid, m, w)) {
                max = mid;
                lo = mid + 1;
            } else hi = mid - 1;
        }
        System.out.println(max);
    }

    public static boolean check(int[] a, int[] b, int target, int m, int w) {
        boolean ok = true;

        for (int i = 0; i < a.length; i++) {
            if (a[i] >= target) continue;
            int diff = target - a[i];
            if (diff > m) {
                ok = false;
                break;
            }
            for (int j=0; j<w && (i+j) < a.length; j++) {
                a[i+j] = a[i+j] + diff;
                b[i+j] = b[i+j] + diff;
            }
            m = m - diff;
        }
        for (int i = 0; i < a.length; i++) {
            a[i] = a[i] - b[i];
            b[i] = 0;
        }
        return ok;
    }
}


import java.util.Arrays;
import java.util.Scanner;

public class Solution {

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

        int n = sc.nextInt(), m = sc.nextInt(), w = sc.nextInt();

        int[] a = new int[n];

        for (int i = 0; i < n; i++) {
            a[i] = sc.nextInt();
        }

        int lo = 0, hi = 2000000000, max = 0;

        while (lo <= hi) {
            int mid = lo + (hi - lo) / 2;
            if (check(a, mid, n, m, w)) {
                max = mid;
                lo = mid + 1;
            } else hi = mid - 1;
        }
        System.out.println(max);
    }

    public static boolean check(int[] original, int target, int n, int m, int w) {
        int[] a = Arrays.copyOf(original, original.length);
        int i;
        for (i = 0; i < a.length && m > 0; i++) {
            while (a[i] < target && m > 0) {
                for (int j = 0; j < w && (i + j) < a.length; j++) {
                    a[i + j] = a[i + j] + 1;
                }
                m--;
            }
        }
        for (i = i; i < a.length; i++) {
            if (a[i] < target) return false;
        }
        return true;
    }
}


//package acc;
import java.util.*;
import java.io.*;

   public  class ACC {
//************Main*****************//

         public static void main(String[] args) throws IOException
			 {
             //   PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
              //  Scanner in=new Scanner (System.in);
               InputStream inputStream = System.in;
                OutputStream outputStream = System.out;
                InputReader in = new InputReader(inputStream);
                PrintWriter out = new PrintWriter(outputStream);
                int n=in.nextInt(),m=in.nextInt(),w=in.nextInt();
                int arr[]=new int[n];
                for(int  i=0;i<n;i++)
                    arr[i]=in.nextInt();
                Arrays.sort(arr);
                PriorityQueue<Integer> s=new PriorityQueue<>();
                //Set<Integer> s=new HashSet<>();
               for(int i=0;i<n;i+=w)
                    s.add(arr[i]);

                while(m--!=0){
                    int x=s.poll();
                    x++;
                    s.add(x);
                }

                out.print(s.peek());
                out.close();
         }

   }
    class Pair implements Comparable<Pair>{
    int x,y;
    public  Pair(int X,int Y){
        super();
x=X;
y=Y;
}
    @Override
      public int compareTo(Pair p){
          if(Math.abs(x)==Math.abs(p.x)) return Integer.compare(Math.abs(y), Math.abs(p.y));
       return Integer.compare(Math.abs(x), Math.abs(p.x));
}
  }

class InputReader {
    private BufferedReader reader;
    private StringTokenizer tokenizer;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream));
        tokenizer = null;
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }
    public long nextLong(){
        return Long.parseLong(next());
    }
}


//package acc;
import java.util.*;
import java.io.*;
import java.math.BigInteger;
   public  class ACC {
//************Main*****************//
       static int con=1000000000,n=0,w=0;
       static long arr1[]=new long[100001],m=0;
        public static boolean check(long mid)
    {
        long arr[]=new long[n+1];
        for(int i=1;i<=n;i++) {
            if(mid> arr1[i]) arr[i]=mid-arr1[i];
        }
        long x=arr[1];
        for(int i=2;i<=n;i++){
            if(i>w){
                x-=arr[i-w];
            }
            if(arr[i]>x){
                arr[i]-=x;
                x+=arr[i];
            }
            else arr[i]=0;
        }
        long sum=0;
        for(int i=1;i<=n;i++){
            sum+=arr[i];
        }
        if(sum>m) return false;
        else return true;
    }
         public static void main(String[] args) throws IOException
			 {
             //   PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
              //  Scanner in=new Scanner (System.in);
               InputStream inputStream = System.in;
                OutputStream outputStream = System.out;
                InputReader in = new InputReader(inputStream);
                PrintWriter out = new PrintWriter(outputStream);
                n=in.nextInt();m=in.nextInt();w=in.nextInt();
                long sum=0;

                for(int i=1;i<=n;i++) {
                    arr1[i]=in.nextInt();
                    if(sum<arr1[i]) sum=arr1[i];
                }
                long left=1;

                long righ=(long)m*sum*2;
                while(left<righ){
                    long mid=(righ+left+1)/2;
                    if(check(mid)) left=mid;
                    else righ=mid-1;
                }
                out.print(left);
                out.close();
         }

   }
    class Pair implements Comparable<Pair>{
    int x,y;
    public  Pair(int X,int Y){
        super();
x=X;
y=Y;
}
    @Override
      public int compareTo(Pair p){
          if((x)==(p.x)) return Integer.compare((y), (p.y));
       return Integer.compare((x), (p.x));
}
  }

class InputReader {
    private BufferedReader reader;
    private StringTokenizer tokenizer;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream));
        tokenizer = null;
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }
    public long nextLong(){
        return Long.parseLong(next());
    }
}


//package acc;
import java.util.*;
import java.io.*;
import java.math.BigInteger;
   public  class ACC {
//************Main*****************//
       static int con=1000000000,n=0,w=0;
       static long arr1[]=new long[100001],m=0;
       static boolean valid(long  t){
           long arr[]=new long[n+1];
           for(int j=1;j<=n;j++) arr[j]=t-arr1[j];
           boolean ok=true;
           for(int i=2;i<=n;i++){
               int u=i-w+1;
               if(u<1){
                   u=1;
               }
               if(arr[u]>0&&u!=i) arr[i]-=arr[u];
           }
           long sum=0;
           for(int i=1;i<=n;i++){
               if(arr[i]>0) sum+=arr[i];
           }
           if(sum>m) ok=false;
           return ok;
       }
         public static void main(String[] args) throws IOException
			 {
             //   PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
              //  Scanner in=new Scanner (System.in);
               InputStream inputStream = System.in;
                OutputStream outputStream = System.out;
                InputReader in = new InputReader(inputStream);
                PrintWriter out = new PrintWriter(outputStream);
                n=in.nextInt();m=in.nextInt();w=in.nextInt();
                long sum=0;
                for(int i=1;i<=n;i++) {
                    arr1[i]=in.nextInt();
                    if(sum<arr1[i]) sum=arr1[i];
                }
                long left=1;

                long righ=(long)m*sum*2;
                while(left<righ){
                    long mid=(righ+left+1)/2;
                    if(valid(mid)) left=mid;
                    else righ=mid-1;
                }
                out.print(left);
                out.close();
         }

   }
    class Pair implements Comparable<Pair>{
    int x,y;
    public  Pair(int X,int Y){
        super();
x=X;
y=Y;
}
    @Override
      public int compareTo(Pair p){
          if((x)==(p.x)) return Integer.compare((y), (p.y));
       return Integer.compare((x), (p.x));
}
  }

class InputReader {
    private BufferedReader reader;
    private StringTokenizer tokenizer;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream));
        tokenizer = null;
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }
    public long nextLong(){
        return Long.parseLong(next());
    }
}


//package acc;
import java.util.*;
import java.io.*;
import java.math.BigInteger;
   public  class ACC {
//************Main*****************//
       static int con=1000000000,n=0,w=0;
       static long arr1[]=new long[100001],m=0;
       static boolean valid(long  t){
           long arr[]=new long[n+1];
           long a[]=new long[n+1];
           for(int j=1;j<=n;j++) {
               arr[j]=t-arr1[j];
               a[j]=arr[j];
           }
           boolean ok=true;
           long x=arr[1];
           for(int i=2;i<=n;i++){
               int u=i-w;
               if(u<1){
                   u=0;
               }
               if(arr[u]>0) x-=arr[u];
               arr[i]-=x;
               if(a[i]>x) x=a[i];
           }
           long sum=0;
           for(int i=1;i<=n;i++){
               if(arr[i]>0) sum+=arr[i];
           }
           if(sum>m) ok=false;
           return ok;
       }
         public static void main(String[] args) throws IOException
			 {
             //   PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
              //  Scanner in=new Scanner (System.in);
               InputStream inputStream = System.in;
                OutputStream outputStream = System.out;
                InputReader in = new InputReader(inputStream);
                PrintWriter out = new PrintWriter(outputStream);
                n=in.nextInt();m=in.nextInt();w=in.nextInt();
                long sum=0;
                for(int i=1;i<=n;i++) {
                    arr1[i]=in.nextInt();
                    if(sum<arr1[i]) sum=arr1[i];
                }
                long left=1;

                long righ=(long)m*sum*2;
                while(left<righ){
                    long mid=(righ+left+1)/2;
                    if(valid(mid)) left=mid;
                    else righ=mid-1;
                }
                out.print(left);
                out.close();
         }

   }
    class Pair implements Comparable<Pair>{
    int x,y;
    public  Pair(int X,int Y){
        super();
x=X;
y=Y;
}
    @Override
      public int compareTo(Pair p){
          if((x)==(p.x)) return Integer.compare((y), (p.y));
       return Integer.compare((x), (p.x));
}
  }

class InputReader {
    private BufferedReader reader;
    private StringTokenizer tokenizer;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream));
        tokenizer = null;
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }
    public long nextLong(){
        return Long.parseLong(next());
    }
}


//package acc;
import java.util.*;
import java.io.*;
import java.math.BigInteger;
   public  class ACC {
//************Main*****************//
       static int con=1000000000,n=0,w=0;
       static long arr1[]=new long[100001],m=0;
       static boolean valid(long  t){
           long arr[]=new long[n+1];
           for(int j=1;j<=n;j++) arr[j]=t-arr1[j];
           boolean ok=true;
           for(int i=2;i<=n;i++){
               int u=i-w+1;
               if(u<1){
                   u=1;
               }
               if(arr[u]>0&&u!=i) arr[i]-=arr[u];
           }
           long sum=0;
           for(int i=1;i<=n;i++){
               if(arr[i]>0) sum+=arr[i];
           }
           if(sum>m) ok=false;
           return ok;
       }
         public static void main(String[] args) throws IOException
			 {
             //   PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
              //  Scanner in=new Scanner (System.in);
               InputStream inputStream = System.in;
                OutputStream outputStream = System.out;
                InputReader in = new InputReader(inputStream);
                PrintWriter out = new PrintWriter(outputStream);
                n=in.nextInt();m=in.nextInt();w=in.nextInt();
                long sum=0;
                for(int i=1;i<=n;i++) {
                    arr1[i]=in.nextInt();
                    if(sum<arr1[i]) sum=arr1[i];
                }
                long left=1;

                long righ=(long)m*sum;
                while(left<righ){
                    long mid=(righ+left+1)/2;
                    if(valid(mid)) left=mid;
                    else righ=mid-1;
                }
                out.print(left);
                out.close();
         }

   }
    class Pair implements Comparable<Pair>{
    int x,y;
    public  Pair(int X,int Y){
        super();
x=X;
y=Y;
}
    @Override
      public int compareTo(Pair p){
          if((x)==(p.x)) return Integer.compare((y), (p.y));
       return Integer.compare((x), (p.x));
}
  }

class InputReader {
    private BufferedReader reader;
    private StringTokenizer tokenizer;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream));
        tokenizer = null;
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }
    public long nextLong(){
        return Long.parseLong(next());
    }
}


import java.util.Arrays;
import java.util.Scanner;

public class C {

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

		int n = in.nextInt();
		int m = in.nextInt();
		int w = in.nextInt();
		int[] arr = new int[n];
		int[] pom = new int[100005];

		for (int i = 0; i < n; i++)
			arr[i] = in.nextInt();

		int low = getMin(arr, n);
		int high = getMax(arr, n);
		int kol = 0;
		int sum = 0;

		while (low <= high) {
			int mid = low + (high - low) / 2;
			kol = 0;
			sum = 0;
			Arrays.fill(pom, 0);

			for (int i = 0; i < n && kol <= m; i++) {
				sum += pom[i];

				if (arr[i] + sum < mid) {
					kol += mid - (arr[i] + sum);
					pom[i + w] -= mid - (arr[i] + sum);
					sum = mid - arr[i];
				}
			}

			if (kol <= m)
				low = mid + 1;
			else
				high = mid - 1;
		}

		System.out.println(high);

		in.close();
	}

	public static int getMax(int[] arr, int n) {
		int max = Integer.MIN_VALUE;

		for (int i = 0; i < n; i++)
			if (arr[i] > max)
				max = arr[i];

		return max;
	}

	public static int getMin(int[] arr, int n) {
		int min = Integer.MAX_VALUE;

		for (int i = 0; i < n; i++)
			if (arr[i] < min)
				min = arr[i];

		return min;
	}
}


import java.util.Arrays;
import java.util.Scanner;

public class C {

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

		int n = in.nextInt();
		int m = in.nextInt();
		int w = in.nextInt();
		int[] arr = new int[n];
		int[] pom = new int[n];

		for (int i = 0; i < n; i++)
			arr[i] = in.nextInt();

		int low = getMin(arr, n);
		int high = getMax(arr, n);
		int kol = 0;
		int sum = 0;

		while (low <= high) {
			int mid = low + (high - low) / 2;
			kol = 0;
			sum = 0;
			Arrays.fill(pom, 0);

			for (int i = 0; i < n && kol <= m; i++) {
				sum += pom[i];

				if (arr[i] + sum < mid) {
					kol += mid - (arr[i] + sum);
					pom[i + w] -= mid - (arr[i] + sum);
					sum = mid - arr[i];
				}
			}

			if (kol <= m)
				low = mid + 1;
			else
				high = mid - 1;
		}

		System.out.println(high);

		in.close();
	}

	public static int getMax(int[] arr, int n) {
		int max = Integer.MIN_VALUE;

		for (int i = 0; i < n; i++)
			if (arr[i] > max)
				max = arr[i];

		return max;
	}

	public static int getMin(int[] arr, int n) {
		int min = Integer.MAX_VALUE;

		for (int i = 0; i < n; i++)
			if (arr[i] < min)
				min = arr[i];

		return min;
	}
}


import java.util.Arrays;
import java.util.Scanner;

public class C {

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

		int n = in.nextInt();
		int m = in.nextInt();
		int w = in.nextInt();
		int[] arr = new int[n];
		int[] pom = new int[200000];

		for (int i = 0; i < n; i++)
			arr[i] = in.nextInt();

		int low = 1;
		int high = 1500000000;
		int kol = 0;
		int sum = 0;

		while (low <= high) {
			int mid = low + (high - low) / 2;
			kol = 0;
			sum = 0;
			Arrays.fill(pom, 0);

			for (int i = 0; i < n && kol <= m; i++) {
				sum += pom[i];

				if (arr[i] + sum < mid) {
					kol += mid - (arr[i] + sum);
					pom[i + w] -= mid - (arr[i] + sum);
					sum = mid - arr[i];
				}
			}

			if (kol <= m)
				low = mid + 1;
			else
				high = mid - 1;
		}

		System.out.println(high);

		in.close();
	}
}


package main;

import java.util.Arrays;
import java.util.Scanner;

public class C {

	public static void main(String[] args) {

		Scanner in = new Scanner(System.in);

		int n = in.nextInt();
		int m = in.nextInt();
		int w = in.nextInt();
		int[] arr = new int[n];

		for (int i = 0; i < n; i++)
			arr[i] = in.nextInt();

//		for (int i = 0; i < n; i++)
//			System.out.print(arr[i] + " ");

		int minNum = getMin(arr, n);
		int start = minNum;
		int maxNum = getMax(arr, n);
		int binSize = maxNum + m;
		int[] bin = new int[binSize];
		int[] pom = new int[n];
		Arrays.fill(pom, 0);

//		System.out.println("Max: " + getMax(arr, n));
//		System.out.println("Min: " + getMin(arr, n));
//		System.out.println("Bin size: " + binSize);

		for (int i = 0; i < binSize; i++) {
			bin[i] = start++;
//			System.out.print(bin[i] + " ");
		}

//		System.out.println();
		int binRes = binarySearch(arr, pom, bin, n, bin[0], bin[binSize - 1], 8, minNum, w, m);
		System.out.println(binRes);

		in.close();
	}

	public static int binarySearch(int[] arr, int[] pom, int[] bin, int n, int low, int high, int x, int minNum, int w, int m) {
		int sum = 0;
		int maxResult = minNum;

		while (low <= high) {
			int mid = low + (high - low) / 2;
			sum = 0;
			Arrays.fill(pom, 0);
			pom[0] = getValue(mid, arr[0]);

			if (w < n)
				pom[w] = -pom[0];

			sum = pom[0];

			for (int i = 1; i < n; i++) {
				int prev = pom[i - 1];
				int curr = pom[i];
				int num = prev + curr + arr[i];

//				System.out.println();
//				System.out.println("Mid: " + mid);
//				System.out.println(prev + " | " + curr + " | " + num);

				if (num > mid) {
					pom[i] = prev + curr;
				}
				else {
					int razl = mid - num;
					pom[i] = prev + curr + razl;
					sum += razl;

					if (i + w < n)
						pom[i + w] -= razl;
				}
			}

//			System.out.println("SUMA: " + sum + ", m: " + m);

			if (sum > m) {
				high = mid - 1;
			}
			else if (sum <= m) {
				low = mid + 1;

				if (maxResult < mid)
					maxResult = mid;
			}
		}

		return maxResult;
	}

	public static int getValue(int a, int b) {
		return a > b ? a - b : 0;
	}

	public static int getMax(int[] arr, int n) {
		int max = Integer.MIN_VALUE;

		for (int i = 0; i < n; i++)
			if (arr[i] > max)
				max = arr[i];

		return max;
	}

	public static int getMin(int[] arr, int n) {
		int min = Integer.MAX_VALUE;

		for (int i = 0; i < n; i++)
			if (arr[i] < min)
				min = arr[i];

		return min;
	}
}

//6 2 3
//2 2 2 2 1 1

//2 5 1
//5 8


import java.util.Arrays;
import java.util.Scanner;

public class C {

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

		int n = in.nextInt();
		int m = in.nextInt();
		int w = in.nextInt();
		int[] arr = new int[n];

		for (int i = 0; i < n; i++)
			arr[i] = in.nextInt();

		int minNum = getMin(arr, n);
		int start = minNum;
		int maxNum = getMax(arr, n);
		int binSize = maxNum + m;
		int[] bin = new int[binSize];
		int[] pom = new int[n];
		Arrays.fill(pom, 0);

		for (int i = 0; i < binSize; i++)
			bin[i] = start++;

		int binRes = binarySearch(arr, pom, bin, n, bin[0], bin[binSize - 1], 8, minNum, w, m);
		System.out.println(binRes);

		in.close();
	}

	public static int binarySearch(int[] arr, int[] pom, int[] bin, int n, int low, int high, int x, int minNum, int w, int m) {
		int sum = 0;
		int maxResult = minNum;

		while (low <= high) {
			int mid = low + (high - low) / 2;
			sum = 0;
			Arrays.fill(pom, 0);
			pom[0] = getValue(mid, arr[0]);

			if (w < n)
				pom[w] = -pom[0];

			sum = pom[0];

			for (int i = 1; i < n; i++) {
				int prev = pom[i - 1];
				int curr = pom[i];
				int num = prev + curr + arr[i];

				if (num > mid) {
					pom[i] = prev + curr;
				}
				else {
					int razl = mid - num;
					pom[i] = prev + curr + razl;
					sum += razl;

					if (i + w < n)
						pom[i + w] -= razl;
				}
			}

			if (sum > m) {
				high = mid - 1;
			}
			else if (sum <= m) {
				low = mid + 1;

				if (maxResult < mid)
					maxResult = mid;
			}
		}

		return maxResult;
	}

	public static int getValue(int a, int b) {
		return a > b ? a - b : 0;
	}

	public static int getMax(int[] arr, int n) {
		int max = Integer.MIN_VALUE;

		for (int i = 0; i < n; i++)
			if (arr[i] > max)
				max = arr[i];

		return max;
	}

	public static int getMin(int[] arr, int n) {
		int min = Integer.MAX_VALUE;

		for (int i = 0; i < n; i++)
			if (arr[i] < min)
				min = arr[i];

		return min;
	}
}


import java.util.Arrays;
import java.util.Scanner;

public class C {

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

		int n = in.nextInt();
		int m = in.nextInt();
		int w = in.nextInt();
		int[] arr = new int[n];
		int[] pom = new int[200010];

		for (int i = 0; i < n; i++)
			arr[i] = in.nextInt();

		int low = 1;
		int high = 1500000000;
		int kol = 0;
		int sum = 0;

		while (low <= high) {
			int mid = low + (high - low) / 2;
			kol = 0;
			sum = 0;
			Arrays.fill(pom, 0);

			for (int i = 0; i < n && kol <= m; i++) {
				sum += pom[i];

				if (arr[i] + sum < mid) {
					kol += mid - (arr[i] + sum);
					pom[i + w] -= mid - (arr[i] + sum);
					sum = mid - arr[i];
				}
			}

			if (kol <= m)
				low = mid + 1;
			else
				high = mid - 1;
		}

		System.out.println(high);

		in.close();
	}
}


import java.util.Arrays;
import java.util.Scanner;
import java.util.Vector;

public class C {

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

		int n = in.nextInt();
		int m = in.nextInt();
		int w = in.nextInt();
		int[] arr = new int[n];

		for (int i = 0; i < n; i++)
			arr[i] = in.nextInt();

		int minNum = getMin(arr, n);
		int start = minNum;
		int maxNum = getMax(arr, n);
		int binSize = maxNum + m;
		int[] pom = new int[n];
		Arrays.fill(pom, 0);

		int binRes = binarySearch(arr, pom, n, 1, 1500000000, 8, minNum, w, m);
		System.out.println(binRes);

		in.close();
	}

	public static int binarySearch(int[] arr, int[] pom, int n, int low, int high, int x, int minNum, int w, int m) {
		int sum = 0;
		int maxResult = minNum;

		while (low <= high) {
			int mid = low + (high - low) / 2;
			sum = 0;
			Arrays.fill(pom, 0);
			pom[0] = getValue(mid, arr[0]);

			if (w < n)
				pom[w] = -pom[0];

			sum = pom[0];

			for (int i = 1; i < n; i++) {
				int prev = pom[i - 1];
				int curr = pom[i];
				int num = prev + curr + arr[i];

				if (num > mid) {
					pom[i] = prev + curr;
				}
				else {
					int razl = mid - num;
					pom[i] = prev + curr + razl;
					sum += razl;

					if (i + w < n)
						pom[i + w] -= razl;
				}
			}

			if (sum > m) {
				high = mid - 1;
			}
			else if (sum <= m) {
				low = mid + 1;

				if (maxResult < mid)
					maxResult = mid;
			}
		}

		return maxResult;
	}

	public static int getValue(int a, int b) {
		return a > b ? a - b : 0;
	}

	public static int getMax(int[] arr, int n) {
		int max = Integer.MIN_VALUE;

		for (int i = 0; i < n; i++)
			if (arr[i] > max)
				max = arr[i];

		return max;
	}

	public static int getMin(int[] arr, int n) {
		int min = Integer.MAX_VALUE;

		for (int i = 0; i < n; i++)
			if (arr[i] < min)
				min = arr[i];

		return min;
	}
}


import java.util.Arrays;
import java.util.Scanner;

public class C {

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

		int n = in.nextInt();
		int m = in.nextInt();
		int w = in.nextInt();
		int[] arr = new int[n];
		int[] pom = new int[200010];

		for (int i = 0; i < n; i++)
			arr[i] = in.nextInt();

		int low = 1;
		int high = 2000000000;
		int kol = 0;
		int sum = 0;

		while (low <= high) {
			int mid = low + (high - low) / 2;
			kol = 0;
			sum = 0;
			Arrays.fill(pom, 0);

			for (int i = 0; i < n && kol <= m; i++) {
				sum += pom[i];

				if (arr[i] + sum < mid) {
					kol += mid - (arr[i] + sum);
					pom[i + w] -= mid - (arr[i] + sum);
					sum = mid - arr[i];
				}
			}

			if (kol <= m)
				low = mid + 1;
			else
				high = mid - 1;
		}

		System.out.println(high);

		in.close();
	}
}


import java.util.Arrays;
import java.util.Scanner;

public class C {

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

		int n = in.nextInt();
		int m = in.nextInt();
		int w = in.nextInt();
		int[] arr = new int[n];
		int[] pom = new int[n];

		for (int i = 0; i < n; i++)
			arr[i] = in.nextInt();

		int low = 1;
		int high = getMax(arr, n);
		int kol = 0;
		int sum = 0;

		while (low <= high) {
			int mid = low + (high - low) / 2;
			kol = 0;
			sum = 0;
			Arrays.fill(pom, 0);

			for (int i = 0; i < n && kol <= m; i++) {
				sum += pom[i];

				if (arr[i] + sum < mid) {
					kol += mid - (arr[i] + sum);
					pom[i + w] -= mid - (arr[i] + sum);
					sum = mid - arr[i];
				}
			}

			if (kol <= m)
				low = mid + 1;
			else
				high = mid - 1;
		}

		System.out.println(high);

		in.close();
	}

	public static int getMax(int[] arr, int n) {
		int max = Integer.MIN_VALUE;

		for (int i = 0; i < n; i++)
			if (arr[i] > max)
				max = arr[i];

		return max;
	}

	public static int getMin(int[] arr, int n) {
		int min = Integer.MAX_VALUE;

		for (int i = 0; i < n; i++)
			if (arr[i] < min)
				min = arr[i];

		return min;
	}
}


import java.util.Arrays;
import java.util.Scanner;

public class C {

	public static void main(String[] args) {

		Scanner in = new Scanner(System.in);

		int n = in.nextInt();
		int m = in.nextInt();
		int w = in.nextInt();
		int[] arr = new int[n];

		for (int i = 0; i < n; i++)
			arr[i] = in.nextInt();

//		for (int i = 0; i < n; i++)
//			System.out.print(arr[i] + " ");

		int minNum = getMin(arr, n);
		int start = minNum;
		int maxNum = getMax(arr, n);
		int binSize = maxNum + m;
		int[] bin = new int[binSize];
		int[] pom = new int[n];
		Arrays.fill(pom, 0);

//		System.out.println("Max: " + getMax(arr, n));
//		System.out.println("Min: " + getMin(arr, n));
//		System.out.println("Bin size: " + binSize);

		for (int i = 0; i < binSize; i++) {
			bin[i] = start++;
//			System.out.print(bin[i] + " ");
		}

//		System.out.println();
		int binRes = binarySearch(arr, pom, bin, n, bin[0], bin[binSize - 1], 8, minNum, w, m);
		System.out.println(binRes);

		in.close();
	}

	public static int binarySearch(int[] arr, int[] pom, int[] bin, int n, int low, int high, int x, int minNum, int w, int m) {
		int sum = 0;
		int maxResult = minNum;

		while (low <= high) {
			int mid = low + (high - low) / 2;
			sum = 0;
			Arrays.fill(pom, 0);
			pom[0] = getValue(mid, arr[0]);

			if (w < n)
				pom[w] = -pom[0];

			sum = pom[0];

			for (int i = 1; i < n; i++) {
				int prev = pom[i - 1];
				int curr = pom[i];
				int num = prev + curr + arr[i];

//				System.out.println();
//				System.out.println("Mid: " + mid);
//				System.out.println(prev + " | " + curr + " | " + num);

				if (num > mid) {
					pom[i] = prev + curr;
				}
				else {
					int razl = mid - num;
					pom[i] = prev + curr + razl;
					sum += razl;

					if (i + w < n)
						pom[i + w] -= razl;
				}
			}

//			System.out.println("SUMA: " + sum + ", m: " + m);

			if (sum > m) {
				high = mid - 1;
			}
			else if (sum <= m) {
				low = mid + 1;

				if (maxResult < mid)
					maxResult = mid;
			}
		}

		return maxResult;
	}

	public static int getValue(int a, int b) {
		return a > b ? a - b : 0;
	}

	public static int getMax(int[] arr, int n) {
		int max = Integer.MIN_VALUE;

		for (int i = 0; i < n; i++)
			if (arr[i] > max)
				max = arr[i];

		return max;
	}

	public static int getMin(int[] arr, int n) {
		int min = Integer.MAX_VALUE;

		for (int i = 0; i < n; i++)
			if (arr[i] < min)
				min = arr[i];

		return min;
	}
}

//6 2 3
//2 2 2 2 1 1

//2 5 1
//5 8


import java.util.Arrays;
import java.util.Scanner;

public class C {

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

		int n = in.nextInt();
		int m = in.nextInt();
		int w = in.nextInt();
		int[] arr = new int[n];
		int[] pom = new int[100005];

		for (int i = 0; i < n; i++)
			arr[i] = in.nextInt();

		int low = 1;
		int high = 1500000000;
		int kol = 0;
		int sum = 0;

		while (low <= high) {
			int mid = low + (high - low) / 2;
			kol = 0;
			sum = 0;
			Arrays.fill(pom, 0);

			for (int i = 0; i < n && kol <= m; i++) {
				sum += pom[i];

				if (arr[i] + sum < mid) {
					kol += mid - (arr[i] + sum);
					pom[i + w] -= mid - (arr[i] + sum);
					sum = mid - arr[i];
				}
			}

			if (kol <= m)
				low = mid + 1;
			else
				high = mid - 1;
		}

		System.out.println(high);

		in.close();
	}

	public static int getMax(int[] arr, int n) {
		int max = Integer.MIN_VALUE;

		for (int i = 0; i < n; i++)
			if (arr[i] > max)
				max = arr[i];

		return max;
	}

	public static int getMin(int[] arr, int n) {
		int min = Integer.MAX_VALUE;

		for (int i = 0; i < n; i++)
			if (arr[i] < min)
				min = arr[i];

		return min;
	}
}


#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int N=100005;
#define mp make_pair
typedef pair<int,int> Pair;
int read()
{
    char ch=' ';
	int x=0;
	bool flag=false;
    while(!isdigit(ch))
	{
		if(ch=='-')flag=true;
		ch=getchar();
	}
    while(isdigit(ch))
	{
		x=(x<<3)+(x<<1)+ch-'0';
		ch=getchar();
	}
	return flag?-x:x;
}
struct heap
{
	vector <Pair> v;
	int loc[N];
	heap()
	{
		v.push_back(mp(-1,-1));
		memset(loc,-1,sizeof loc);
	}
	void push(Pair p)//key value
	{
		int cur;
		cur=v.size();
		loc[p.second]=cur;
		v.push_back(p);
		while(v[cur]<v[cur>>1])
		{
			swap(v[cur],v[cur>>1]);
			swap(loc[v[cur].second],loc[v[cur>>1].second]);
			cur>>=1;
		}
	}
	void pop()
	{
		if(empty())	return;
		swap(v[1],v.back());
		loc[v[1].second]=1;
		loc[v.back().second]=-1;
		v.pop_back();
		int cur=1;
		while((cur<<1)<v.size())
		{
			if((cur<<1)+1==v.size())
			{
				if(v[cur]>v[cur<<1])
					swap(v[cur],v[cur<<1]),swap(loc[v[cur].second],loc[v[cur<<1].second]);
				break;
			}
			if(v[cur]<min(v[cur<<1],v[(cur<<1)+1]))break;
			if(v[cur<<1]<v[(cur<<1)+1])
			{
				swap(v[cur],v[cur<<1]);
				swap(loc[v[cur].second],loc[v[cur<<1].second]);
				cur<<=1;
			}
			else{
				swap(v[cur],v[(cur<<1)+1]);
				swap(loc[v[cur].second],loc[v[(cur<<1)+1].second]);
				cur=(cur<<1)+1;
			}
		}
	}
	Pair top()
	{
		return v[1];
	}
	bool empty()
	{
		return v.size()==1;
	}
};
int n,m;
vector <int> bad[N];
vector <Pair> v[N];
int d[N];
heap pq;
int main()
{
	n=read(),m=read();
	for(int i=0;i<m;i++)
	{
		int a=read(),b=read(),c=read();
		--a,--b;
		v[a].push_back(mp(b,c));
		v[b].push_back(mp(a,c));
	}
	for(int i=0;i<n;i++)
	{
		int num=read();
		while(num--)
		{
			bad[i].push_back(read());
		}
	}
	for(int i=0;i<n;i++)
		d[i]=INF;
	d[0]=0;
	pq.push(mp(0,0));
	while(!pq.empty())
	{
		Pair tp=pq.top();
		pq.pop();
		int t=tp.first;
		int cur=tp.second;
		if(t!=d[cur])continue;
		int j=0;
		while(j<bad[cur].size() && bad[cur][j]<t)j++;
		while(j<bad[cur].size() && bad[cur][j]==t)t++,j++;
		for(int i=0;i<v[cur].size();i++)
		{
			int to=v[cur][i].first,cost=v[cur][i].second;
			if(t+cost<d[to])
			{
				d[to]=t+cost;
				pq.push(mp(d[to],to));
			}
		}
	}
	if(d[n-1]>=INF)
		puts("-1");
	else cout<<d[n-1]<<endl;
	return 0;
}


#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int N=100005;
#define mp make_pair
typedef pair<int,int> Pair;
struct heap
{
	vector <Pair> v;
	int loc[N];
	heap()
	{
		v.push_back(mp(-1,-1));
		memset(loc,-1,sizeof loc);
	}
	void push(Pair p)//key value
	{
		int cur;
		cur=v.size();
		loc[p.second]=cur;
		v.push_back(p);
		while(v[cur]<v[cur>>1])
		{
			swap(v[cur],v[cur>>1]);
			swap(loc[v[cur].second],loc[v[cur>>1].second]);
			cur>>=1;
		}
	}
	void pop()
	{
		if(empty())	return;
		swap(v[1],v.back());
		loc[v[1].second]=1;
		loc[v.back().second]=-1;
		v.pop_back();
		int cur=1;
		while(2*cur<v.size())
		{
			if(cur*2+1==v.size())
			{
				if(v[cur]>v[cur*2])
					swap(v[cur],v[cur*2]),swap(loc[v[cur].second],loc[v[cur*2].second]);
				break;
			}
			if(v[cur]<min(v[cur*2],v[cur*2+1]))break;
			if(v[cur*2]<v[cur*2+1])
			{
				swap(v[cur],v[cur*2]);
				swap(loc[v[cur].second],loc[v[cur*2].second]);
				cur*=2;
			}
			else{
				swap(v[cur],v[cur*2+1]);
				swap(loc[v[cur].second],loc[v[cur*2+1].second]);
				cur=cur*2+1;
			}
		}
	}
	Pair top()
	{
		return v[1];
	}
	bool empty()
	{
		return v.size()==1;
	}
};
int n,m;
vector <int> bad[N];
vector <Pair> v[N];
int d[N];
heap pq;
int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for(int i=0;i<m;i++)
	{
		int a,b,c;
		cin>>a>>b>>c;
		--a,--b;
		v[a].push_back(mp(b,c));
		v[b].push_back(mp(a,c));
	}
	for(int i=0;i<n;i++)
	{
		int num;
		cin>>num;
		while(num--)
		{
			int a;
			cin>>a;
			bad[i].push_back(a);
		}
	}
	for(int i=0;i<n;i++)
		d[i]=INF;
	d[0]=0;
	pq.push(mp(0,0));
	while(!pq.empty())
	{
		Pair tp=pq.top();
		pq.pop();
		int t=tp.first;
		int cur=tp.second;
		if(t!=d[cur])continue;
		int j=0;
		while(j<bad[cur].size()&&bad[cur][j]<t)j++;
		while(j<bad[cur].size()&&bad[cur][j]==t)t++,j++;
		for(int i=0;i<v[cur].size();i++)
		{
			int to=v[cur][i].first,cost=v[cur][i].second;
			if(t+cost<d[to])
			{
				d[to]=t+cost;
				pq.push(mp(d[to],to));
			}
		}
	}
	if(d[n-1]>=INF)
		puts("-1");
	else cout<<d[n-1]<<endl;
	return 0;
}


/* Copyright 2017 Rafael Rendón Pablo <rafaelrendonpablo@gmail.com> */
// region Template
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <string>
#include <bitset>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <cmath>
#include <cctype>
#include <cassert>
#include <cstring>
#include <numeric>
#include <iomanip>
#include <algorithm>

using std::string;
using std::vector;
using std::map;
using std::set;
using std::queue;
using std::priority_queue;

typedef long long           int64;
typedef unsigned long long  uint64;
const double kEps   = 10e-8;
const int kMax      = 1000;
const int64 kInf      = 1LL << 60;
// endregion

struct Edge {
    int node;
    int64 cost;
};

struct Node {
    int node;
    int64 cost;

    bool operator<(const Node& that) const {
        return cost < that.cost;
    }

    bool operator>(const Node& that) const {
        return cost > that.cost;
    }
};

int64 findShortesPath(vector<vector<Edge>>& graph, vector<map<int, int>>& delays) {
    priority_queue<Node, vector<Node>, std::greater<Node>> Q;
    int n = graph.size();
    vector<int64> cost(n, kInf);
    cost[0] = 0;
    Q.push({0, 0});
    int64 ans = kInf;
    while (!Q.empty()) {
        Node top = Q.top();
        Q.pop();
        int u = top.node;
        if (cost[u] < top.cost) {
            continue;
        }
        for (Edge e : graph[u]) {
            int v = e.node;
            int64 t = cost[u] + e.cost;
            int d = delays[v][t];
            if(t + d < cost[v]) {
                cost[v] = t + d;
                Q.push({v, t + d});
            }
            if (v == n - 1) {
                ans = std::min(ans, t);
            }
        }
    }
    if (cost[n-1] == kInf) {
        return -1LL;
    }
    return std::min(ans, cost[n-1]);
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int n, m;
    std::cin >> n >> m;
    vector<vector<Edge>> graph(n);
    for (int i = 0; i < m; i++) {
        int a, b, c;
        std::cin >> a >> b >> c;
        a--;
        b--;
        graph[a].push_back({b, c});
        graph[b].push_back({a, c});
    }

    vector<vector<int>> arrivals(n);
    for (int i = 0; i < n; i++) {
        int k;
        std::cin >> k;
        for (int j = 0; j < k; j++) {
            int t;
            std::cin >> t;
            arrivals[i].push_back(t);
        }
    }
    vector<map<int, int>> delays(n);
    for (int i = 0; i < n; i++) {
        vector<int>& arrival = arrivals[i];
        map<int, int>& delay = delays[i];
        int size = arrival.size();
        int count = 1;
        for (int j = size - 1; j >= 0; j--) {
            delay[arrival[j]] = count;
            if (j > 0 && (arrival[j-1] + 1 == arrival[j])) {
                count++;
            } else {
                count = 1;
            }
        }
    }
    std::cout << findShortesPath(graph, delays) << std::endl;
    return EXIT_SUCCESS;
}


/* Copyright 2017 Rafael Rendón Pablo <rafaelrendonpablo@gmail.com> */
// region Template
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <string>
#include <bitset>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <cmath>
#include <cctype>
#include <cassert>
#include <cstring>
#include <numeric>
#include <iomanip>
#include <algorithm>

using std::string;
using std::vector;
using std::map;
using std::set;
using std::queue;
using std::priority_queue;

typedef long long           int64;
typedef unsigned long long  uint64;
const double kEps   = 10e-8;
const int kMax      = 1000;
const int64 kInf      = 1LL << 60;
// endregion

struct Edge {
    int node;
    int64 cost;
};

struct Node {
    int node;
    int64 cost;

    bool operator<(const Node& that) const {
        return cost < that.cost;
    }

    bool operator>(const Node& that) const {
        return cost > that.cost;
    }
};

int64 findShortesPath(vector<vector<Edge>>& graph, vector<map<int, int>>& delays) {
    priority_queue<Node, vector<Node>, std::greater<Node>> Q;
    int n = graph.size();
    vector<int64> cost(n, kInf);
    cost[0] = 0;
    Q.push({0, 0});
    while (!Q.empty()) {
        Node top = Q.top();
        Q.pop();
        int u = top.node;
        if (cost[u] < top.cost) {
            continue;
        }
        for (Edge e : graph[u]) {
            int v = e.node;
            int64 t = cost[u] + e.cost;
            int d = delays[v][t];

            if (v == n - 1) {
                if (t < cost[v]) {
                    cost[v] = t;
                    Q.push({v, t});
                }
            } else {
                if(t + d < cost[v]) {
                    cost[v] = t + d;
                    Q.push({v, t + d});
                }
            }
        }
    }
    if (cost[n-1] == kInf) {
        return -1LL;
    }
    return cost[n-1];
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int n, m;
    std::cin >> n >> m;
    vector<vector<Edge>> graph(n);
    for (int i = 0; i < m; i++) {
        int a, b, c;
        std::cin >> a >> b >> c;
        a--;
        b--;
        graph[a].push_back({b, c});
        graph[b].push_back({a, c});
    }

    vector<vector<int>> arrivals(n);
    for (int i = 0; i < n; i++) {
        int k;
        std::cin >> k;
        for (int j = 0; j < k; j++) {
            int t;
            std::cin >> t;
            arrivals[i].push_back(t);
        }
    }
    vector<map<int, int>> delays(n);
    for (int i = 0; i < n; i++) {
        vector<int>& arrival = arrivals[i];
        map<int, int>& delay = delays[i];
        int size = arrival.size();
        int count = 1;
        for (int j = size - 1; j >= 0; j--) {
            delay[arrival[j]] = count;
            if (j > 0 && (arrival[j-1] + 1 == arrival[j])) {
                count++;
            } else {
                count = 1;
            }
        }
    }
    std::cout << findShortesPath(graph, delays) << std::endl;
    return EXIT_SUCCESS;
}


/* Copyright 2017 Rafael Rendón Pablo <rafaelrendonpablo@gmail.com> */
// region Template
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <string>
#include <bitset>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <cmath>
#include <cctype>
#include <cassert>
#include <cstring>
#include <numeric>
#include <iomanip>
#include <algorithm>

using std::string;
using std::vector;
using std::map;
using std::set;
using std::queue;
using std::priority_queue;

typedef long long           int64;
typedef unsigned long long  uint64;
const double kEps   = 10e-8;
const int kMax      = 1000;
const int64 kInf      = 1LL << 60;
// endregion

struct Edge {
    int node;
    int64 cost;
};

struct Node {
    int node;
    int64 cost;

    bool operator<(const Node& that) const {
        return cost < that.cost;
    }

    bool operator>(const Node& that) const {
        return cost > that.cost;
    }
};

int64 findShortesPath(vector<vector<Edge>>& graph, vector<map<int, int>>& delays) {
    priority_queue<Node, vector<Node>, std::greater<Node>> Q;
    int n = graph.size();
    vector<int64> cost(n, kInf);
    cost[0] = 0;
    Q.push({0, 0});
    while (!Q.empty()) {
        Node top = Q.top();
        Q.pop();
        int u = top.node;
        // if (cost[u] < top.cost) {
        //     continue;
        // }
        int t = top.cost;
        int d = delays[u][t];
        for (Edge e : graph[u]) {
            int v = e.node;
            if(t + d + e.cost < cost[v]) {
                cost[v] = t + d + e.cost;
                Q.push({v, cost[v]});
            }
        }
    }
    if (cost[n-1] == kInf) {
        return -1LL;
    }
    return cost[n-1];
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int n, m;
    std::cin >> n >> m;
    vector<vector<Edge>> graph(n);
    for (int i = 0; i < m; i++) {
        int a, b, c;
        std::cin >> a >> b >> c;
        a--;
        b--;
        graph[a].push_back({b, c});
        graph[b].push_back({a, c});
    }

    vector<vector<int>> arrivals(n);
    for (int i = 0; i < n; i++) {
        int k;
        std::cin >> k;
        for (int j = 0; j < k; j++) {
            int t;
            std::cin >> t;
            arrivals[i].push_back(t);
        }
    }
    vector<map<int, int>> delays(n);
    for (int i = 0; i < n; i++) {
        vector<int>& arrival = arrivals[i];
        map<int, int>& delay = delays[i];
        int size = arrival.size();
        int count = 1;
        for (int j = size - 1; j >= 0; j--) {
            delay[arrival[j]] = count;
            if (j > 0 && (arrival[j-1] + 1 == arrival[j])) {
                count++;
            } else {
                count = 1;
            }
        }
    }
    std::cout << findShortesPath(graph, delays) << std::endl;
    return EXIT_SUCCESS;
}


/* Copyright 2017 Rafael Rendón Pablo <rafaelrendonpablo@gmail.com> */
// region Template
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <string>
#include <bitset>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <cmath>
#include <cctype>
#include <cassert>
#include <cstring>
#include <numeric>
#include <iomanip>
#include <algorithm>

using std::string;
using std::vector;
using std::map;
using std::set;
using std::queue;
using std::priority_queue;

typedef long long           int64;
typedef unsigned long long  uint64;
const double kEps   = 10e-8;
const int kMax      = 1000;
const int64 kInf      = 1LL << 60;
// endregion

struct Edge {
    int node;
    int64 cost;
};

struct Node {
    int node;
    int64 cost;

    bool operator<(const Node& that) const {
        return cost < that.cost;
    }

    bool operator>(const Node& that) const {
        return cost > that.cost;
    }
};

int64 findShortesPath(vector<vector<Edge>>& graph, vector<map<int, int>>& delays) {
    priority_queue<Node, vector<Node>, std::greater<Node>> Q;
    int n = graph.size();
    vector<int64> cost(n, kInf);
    cost[0] = 0;
    Q.push({0, 0});
    while (!Q.empty()) {
        Node top = Q.top();
        Q.pop();
        int u = top.node;
        // if (cost[u] < top.cost) {
        //     continue;
        // }
        for (Edge e : graph[u]) {
            int v = e.node;
            int64 t = cost[u] + e.cost;
            int d = delays[v][t];

            if (v == n - 1) {
                if (t < cost[v]) {
                    cost[v] = t;
                    Q.push({v, t});
                }
            } else {
                if(t + d < cost[v]) {
                    cost[v] = t + d;
                    Q.push({v, t + d});
                }
            }
        }
    }
    if (cost[n-1] == kInf) {
        return -1LL;
    }
    return cost[n-1];
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int n, m;
    std::cin >> n >> m;
    vector<vector<Edge>> graph(n);
    for (int i = 0; i < m; i++) {
        int a, b, c;
        std::cin >> a >> b >> c;
        a--;
        b--;
        graph[a].push_back({b, c});
        graph[b].push_back({a, c});
    }

    vector<vector<int>> arrivals(n);
    for (int i = 0; i < n; i++) {
        int k;
        std::cin >> k;
        for (int j = 0; j < k; j++) {
            int t;
            std::cin >> t;
            arrivals[i].push_back(t);
        }
    }
    vector<map<int, int>> delays(n);
    for (int i = 0; i < n; i++) {
        vector<int>& arrival = arrivals[i];
        map<int, int>& delay = delays[i];
        int size = arrival.size();
        int count = 1;
        for (int j = size - 1; j >= 0; j--) {
            delay[arrival[j]] = count;
            if (j > 0 && (arrival[j-1] + 1 == arrival[j])) {
                count++;
            } else {
                count = 1;
            }
        }
    }
    std::cout << findShortesPath(graph, delays) << std::endl;
    return EXIT_SUCCESS;
}


#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/STACK:256000000")
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <deque>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#include <cassert>

using namespace std;

typedef long long ll;
typedef string str;
#define forn(i, n) for (int i = 0; i < n; i++)
#define form(i, n, m) for (int i = n; i <= m; i++)
//
#define read(x) scanf("%d", &x)
#define write(x) printf("%d", x)
#define writeln(x) printf("%d\n", x)
#define wp(x) cout << x.first << ' ' << x.second << '\n';
#define wm(x) for (int i = 0; i < x.size(); i++) cout << x[i] << ' '; cout << LN;
#define read2(x, y) scanf("%d %d", &x, &y)
//
#define sqr(x) x*x
#define clr(a, x) memset(a, x, sizeof(a));
#define mp make_pair
#define pb push_back
#define pob pop_back
#define XX first
#define YY second
#define in insert
#define db long double
#define re return
#define y1 dsfgsdfgsdfgsdfgsdfgsdfg
#define y0 asdfasdf3rcdt234d5c23xd234dx43
#define sz size
#define rs resize
#define vec vector
#define all(a) a.begin(), a.end()
#define TASK "sum"   //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
const str LN = "\n";
const double eps = 1e-9;
const double pi = acos(-1.0);
const int INF = (int)2e9 + 7;
const ll LINF = (ll)9e18 + 7;
bool in(int k, int x1, int x2) {re (k >= x1 && k <= x2);}

const int MAXN = 60007;
const int P1 = 239017;
const int P2 = 353251;
const ll MOD = 1e9 + 7;
const ll MOD2 = 1e9 + 9;
const int l = 20;

int n, m;
vec< pair<int, int> > g[100007];
ll ans[100007];
vec<int> ti[100007];
set< pair<ll, int> > se;

void relax(int v){
	forn(i, g[v].size()){
		int to = g[v][i].XX;
		int cost = g[v][i].YY;
		if (ans[to] > ans[v] + cost){
			se.erase(mp(ans[to], to));
			ans[to] = ans[v] + cost;
			se.insert(mp(ans[to], to));
		}
	}
}

void dij(int v){
	forn(i, n)
		ans[i] = LINF;
	ans[v] = 0;
	se.in(mp(0, v));
	while (se.size()){
		auto d = *se.begin();
		se.erase(d);
		if (d.YY == n - 1)
			cout << ans[d.YY], exit(0);
		int timer = d.XX;
		forn(i, ti[d.YY].size())
			if (ti[d.YY][i] == timer)
				timer++;
		ans[d.YY] = timer;
		relax(d.YY);
	}
}

const bool is_testing = 0;
int main()
{
	srand(time(NULL));
	if (is_testing)
	{
		freopen("input.txt", "r", stdin);
		freopen("output.txt", "w", stdout);
	}
	cin >> n >> m;
	forn(i, m){
		int a, b, c;
		scanf("%d%d%d", &a, &b, &c);
		a--; b--;
		g[a].pb(mp(b, c));
		g[b].pb(mp(a, c));
	}
	forn(i, n){
		int k;
		read(k);
		forn(j, k){
			int x;
			read(x);
			ti[i].pb(x);
		}
	}
	dij(0);
	/*forn(i, n)
		cout << ans[i] << ' ';*/
	cout << -1;
}


#include <iostream>
#include <vector>
#include <queue>
#include <unordered_set>
#include <algorithm>
#include <functional>
#include <climits>
#include <map>
using namespace std;

int n,m;
vector<pair<int,int> > g[100009];
unordered_set<int> s[100009];
int d[100009];
map<int,int> w;

int main(){
    cin>>n>>m;
    for (int i=0; i<m; i++){
        int x,y,t;
        cin>>x>>y>>t;
        g[x].push_back(make_pair(y,t));
        g[y].push_back(make_pair(x,t));
    }

    for (int i=1; i<=n; i++){
        int x;
        cin>>x;
        for (int j=0; j<x; j++){
            int t;
            cin>>t;
            s[i].insert(t);
        }
    }

    for (int i=1; i<=n; i++)
    d[i]=INT_MAX;

    d[1]=0;

    priority_queue <pair<int,int> , vector<pair<int,int> >, greater<pair<int,int> > > q;
    q.push(make_pair(0,1));

    while (!q.empty()){
        int v=q.top().second;
        int x=q.top().first;
        q.pop();

        if (x>1000000000)
        continue;
        if (x>d[v])
        continue;
        int y=x;
        while (s[v].find(y)!=s[v].end())
            {
                y++;
            }
        for (int i=0; i<g[v].size(); i++){
            int u=g[v][i].first;
            int t=g[v][i].second;

            if (d[u]>y+t){
                d[u]=y+t;
                q.push(make_pair(d[u],u));
            }
        }

    }
    if (d[n]<1000000000)
    cout<<d[n];
    else
    cout<<-1;

    return 0;
}


#include <iostream>
#include <vector>
#include <queue>
#include <unordered_set>
#include <algorithm>
#include <functional>
#include <climits>
#include <map>
using namespace std;

int n,m;
vector<pair<int,int> > g[100009];
unordered_set<int> s[100009];
int d[100009];
map<int,int> w;

int main(){
    cin>>n>>m;
    for (int i=0; i<m; i++){
        int x,y,t;
        cin>>x>>y>>t;
        g[x].push_back(make_pair(y,t));
        g[y].push_back(make_pair(x,t));
    }

    for (int i=1; i<=n; i++){
        int x;
        cin>>x;
        for (int j=0; j<x; j++){
            int t;
            cin>>t;
            s[i].insert(t);
        }
    }

    for (int i=1; i<=n; i++)
    d[i]=INT_MAX;

    d[1]=0;

    priority_queue <pair<int,int> , vector<pair<int,int> >, greater<pair<int,int> > > q;
    q.push(make_pair(0,1));

    while (!q.empty()){
        int v=q.top().second;
        int x=q.top().first;
        q.pop();

        if (x>1000000000)
        continue;
        if (x>d[v])
        continue;

        for (int i=0; i<g[v].size(); i++){
            int u=g[v][i].first;
            int t=g[v][i].second;
            int y=x;
            while (s[v].find(y)!=s[v].end())
            {
                t++;
                y++;
            }
            if (d[u]>x+t){
                d[u]=x+t;
                q.push(make_pair(d[u],u));
            }
        }

    }
    if (d[n]<1000000000)
    cout<<d[n];
    else
    cout<<-1;

    return 0;
}


#include <iostream>
#include <vector>
#include <queue>
#include <unordered_set>
#include <algorithm>
#include <functional>
#include <climits>
#include <map>
using namespace std;

int n,m;
vector<pair<int,int> > g[100009];
unordered_set<int> s[100009];
int d[100009];
map<int,int> w;

int main(){
    cin>>n>>m;
    for (int i=0; i<m; i++){
        int x,y,t;
        cin>>x>>y>>t;
        g[x].push_back(make_pair(y,t));
        g[y].push_back(make_pair(x,t));
    }

    for (int i=1; i<=n; i++){
        int x;
        cin>>x;
        for (int j=0; j<x; j++){
            int t;
            cin>>t;
            s[i].insert(t);
        }
    }

    for (int i=1; i<=n; i++)
    d[i]=INT_MAX;

    d[1]=0;

    priority_queue <pair<int,int> , vector<pair<int,int> >, greater<pair<int,int> > > q;
    q.push(make_pair(0,1));

    while (!q.empty()){
        int v=q.top().second;
        int x=q.top().first;
        q.pop();

        if (x>1000000000)
        continue;
        if (x>d[v])
        continue;
        int y=x;
        while (s[v].find(y)!=s[v].end())
            {
                t++;
                y++;
            }
        for (int i=0; i<g[v].size(); i++){
            int u=g[v][i].first;
            int t=g[v][i].second;

            if (d[u]>x+t){
                d[u]=x+t;
                q.push(make_pair(d[u],u));
            }
        }

    }
    if (d[n]<1000000000)
    cout<<d[n];
    else
    cout<<-1;

    return 0;
}


#include <iostream>
#include <vector>
#include <queue>
#include <set>
#include <algorithm>
#include <functional>
#include <climits>
#include <map>
using namespace std;

int n,m;
vector<pair<int,int> > g[100009];
unordered_set<int> s[100009];
int d[100009];
map<int,int> w;

int main(){
    cin>>n>>m;
    for (int i=0; i<m; i++){
        int x,y,t;
        cin>>x>>y>>t;
        g[x].push_back(make_pair(y,t));
        g[y].push_back(make_pair(x,t));
    }

    for (int i=1; i<=n; i++){
        int x;
        cin>>x;
        for (int j=0; j<x; j++){
            int t;
            cin>>t;
            s[i].insert(t);
        }
    }

    for (int i=1; i<=n; i++)
    d[i]=INT_MAX;

    d[1]=0;

    priority_queue <pair<int,int> , vector<pair<int,int> >, greater<pair<int,int> > > q;
    q.push(make_pair(0,1));

    while (!q.empty()){
        int v=q.top().second;
        int x=q.top().first;
        q.pop();

        if (x>1000000000)
        continue;
        if (x>d[v])
        continue;

        for (int i=0; i<g[v].size(); i++){
            int u=g[v][i].first;
            int t=g[v][i].second;
            int y=x;
            while (s[v].find(y)!=s[v].end())
            {
                t++;
                y++;
            }
            if (d[u]>x+t){
                d[u]=x+t;
                q.push(make_pair(d[u],u));
            }
        }

    }
    if (d[n]<1000000000)
    cout<<d[n];
    else
    cout<<-1;

    return 0;
}


#include <iostream>
#include <vector>
#include <queue>
#include <unordered_set>
#include <algorithm>
#include <functional>
#include <climits>
#include <map>
using namespace std;

int n,m;
vector<pair<int,int> > g[100009];
unordered_set<int> s[100009];
int d[100009];
map<int,int> w;

int main(){
    cin>>n>>m;
    for (int i=0; i<m; i++){
        int x,y,t;
        cin>>x>>y>>t;
        g[x].push_back(make_pair(y,t));
        g[y].push_back(make_pair(x,t));
    }

    for (int i=1; i<=n; i++){
        int x;
        cin>>x;
        for (int j=0; j<x; j++){
            int t;
            cin>>t;
            s[i].insert(t);
        }
    }

    for (int i=1; i<=n; i++)
    d[i]=INT_MAX;

    d[1]=0;

    priority_queue <pair<int,int> , vector<pair<int,int> >, greater<pair<int,int> > > q;
    q.push(make_pair(0,1));

    while (!q.empty()){
        int v=q.top().second;
        int x=q.top().first;
        q.pop();

        if (x>1000000000)
        continue;
        if (x>d[v])
        continue;
        int y=x;
        while (s[v].find(y)!=s[v].end())
            {
                y++;
            }
        for (int i=0; i<g[v].size(); i++){
            int u=g[v][i].first;
            int t=g[v][i].second;

            if (d[u]>y+t){
                d[u]=y+t;
                q.push(make_pair(d[u],u));
            }
        }

    }
    if (d[n]<INT_MAX)
    cout<<d[n];
    else
    cout<<-1;

    return 0;
}


#include <iostream>
#include <vector>
#include <queue>
#include <unordered_set>
#include <algorithm>
#include <functional>
#include <climits>
#include <map>
using namespace std;

int n,m;
vector<pair<int,int> > g[100009];
unordered_set<int> s[100009];
int d[100009];
map<int,int> w;

int main(){
    cin>>n>>m;
    for (int i=0; i<m; i++){
        int x,y,t;
        cin>>x>>y>>t;
        g[x].push_back(make_pair(y,t));
        g[y].push_back(make_pair(x,t));
    }

    for (int i=1; i<=n; i++){
        int x;
        cin>>x;
        for (int j=0; j<x; j++){
            int t;
            cin>>t;
            s[i].insert(t);
        }
    }

    for (int i=1; i<=n; i++)
    d[i]=INT_MAX;

    d[1]=0;

    priority_queue <pair<int,int> , vector<pair<int,int> >, greater<pair<int,int> > > q;
    q.push(make_pair(0,1));

    while (!q.empty()){
        int v=q.top().second;
        int x=q.top().first;
        q.pop();

        if (x>1000000000)
        continue;
        if (x>d[v])
        continue;
        int y=x;
        while (s[v].find(y)!=s[v].end())
            {
                y++;
            }
        for (int i=0; i<g[v].size(); i++){
            int u=g[v][i].first;
            int t=g[v][i].second;

            if (d[u]>y+t){
                d[u]=y+t;
                q.push(make_pair(d[u],u));
            }
        }

    }
    if (d[n]<1000090009)
    cout<<d[n];
    else
    cout<<-1;

    return 0;
}


#include <iostream>
#include <vector>
#include <queue>
#include <unordered_set>
#include <algorithm>
#include <functional>
#include <climits>
#include <map>
using namespace std;

int n,m;
vector<pair<int,int> > g[100009];
unordered_set<int> s[100009];
int d[100009];
map<int,int> w;

int main(){
    cin>>n>>m;
    for (int i=0; i<m; i++){
        int x,y,t;
        cin>>x>>y>>t;
        g[x].push_back(make_pair(y,t));
        g[y].push_back(make_pair(x,t));
    }

    for (int i=1; i<=n; i++){
        int x;
        cin>>x;
        for (int j=0; j<x; j++){
            int t;
            cin>>t;
            s[i].insert(t);
        }
    }

    for (int i=1; i<=n; i++)
    d[i]=INT_MAX;

    d[1]=0;

    priority_queue <pair<int,int> , vector<pair<int,int> >, greater<pair<int,int> > > q;
    q.push(make_pair(0,1));

    while (!q.empty()){
        int v=q.top().second;
        int x=q.top().first;
        q.pop();

        if (x==INT_MAX)
        continue;
        if (x>d[v])
        continue;
        int y=x;
        while (s[v].find(y)!=s[v].end())
            {
                y++;
            }
        for (int i=0; i<g[v].size(); i++){
            int u=g[v][i].first;
            int t=g[v][i].second;

            if (d[u]>y+t){
                d[u]=y+t;
                q.push(make_pair(d[u],u));
            }
        }

    }
    if (d[n]<INT_MAX)
    cout<<d[n];
    else
    cout<<-1;

    return 0;
}


#include <iostream>
#include <vector>
#include <queue>
#include <unordered_set>
#include <algorithm>
#include <functional>
#include <climits>
#include <map>
using namespace std;

int n,m;
vector<pair<int,int> > g[100009];
unordered_set<int> s[100009];
int d[100009];
map<int,int> w;

int main(){
    cin>>n>>m;
    for (int i=0; i<m; i++){
        int x,y,t;
        cin>>x>>y>>t;
        g[x].push_back(make_pair(y,t));
        g[y].push_back(make_pair(x,t));
    }

    for (int i=1; i<=n; i++){
        int x;
        cin>>x;
        for (int j=0; j<x; j++){
            int t;
            cin>>t;
            s[i].insert(t);
        }
    }

    for (int i=1; i<=n; i++)
    d[i]=INT_MAX;

    d[1]=0;

    priority_queue <pair<int,int> , vector<pair<int,int> >, greater<pair<int,int> > > q;
    q.push(make_pair(0,1));

    while (!q.empty()){
        int v=q.top().second;
        int x=q.top().first;
        q.pop();

        if (x>1000000000)
        continue;
        if (x>d[v])
        continue;
        int y=x;
        while (s[v].find(y)!=s[v].end())
            {
                y++;
            }
        for (int i=0; i<g[v].size(); i++){
            int u=g[v][i].first;
            int t=g[v][i].second;

            if (d[u]>y+t){
                d[u]=y+t;
                q.push(make_pair(d[u],u));
            }
        }

    }
    if (d[n]<2000000000)
    cout<<d[n];
    else
    cout<<-1;

    return 0;
}


#include <bits/stdc++.h>

#define pb push_back
#define pp pop_back
#define mp make_pair
#define ld long double
#define f first
#define s second
#define ll long long

using namespace std;

const int N = 2e5 + 5;

const ll inf = 1e18;

int n, m;

ll dist[N];

vector < pair < int, int > > g[N];

set < pair < ll, int > > st;

map < int, bool > ok[N];

bool used[N];

int main()
{
  ios_base::sync_with_stdio(0);
  cin >> n >> m;
  for (int i = 1;i <= m;i++)
  {
  	int a, b, c; cin >> a >> b >> c;
  	g[a].pb(mp(b, c));
  	g[b].pb(mp(a, c));
  }
  for (int i = 1;i <= n;i++)
  {
  	dist[i] = inf;
  	int k, x; cin >> k;
  	while(k--)
  	{
  		cin >> x;
  		ok[i][x] = 1;
  	}
  }
  dist[1] = 0;
  st.insert(mp(0, 1));
  while(st.size())
  {
  	int v = st.begin() -> s;
    st.erase(st.begin());
    if (used[v]) continue;
    used[v] = 1;
		ll cur = dist[v];
		while(ok[v][cur]) cur++;
    for (auto to : g[v])
    {
    	if (dist[to.f] > cur + to.s)
    	{
    		dist[to.f] = cur + to.s;
    		st.insert(mp(dist[to.f], to.f));
    	}
    }
  }
  if (dist[n] == inf) dist[n] = -1;
  cout << dist[n];
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

#ifdef LOCAL_CHECK
#define trace(x) cerr << #x << ": " << x << " ";
#define trnl cerr << "\n";
#else
#define trace(x) {}
#define trnl {}
#endif
typedef long long lolo;
typedef unsigned long long ulolo;
typedef pair<int, int> pii;
#define R(i,n) for(int i=0;i<(n);++i)
#define F(i,a,b) for(int i=(a);i<(b);++i)
#define FS(i,a,b,s) for(int i=(a);i<(b);i+=(s))
#define FD(i,n) for(int i=(n-1);i>=0;--i)
#define FDS(i,n,s) for(int i=(n-1);i>=0;i-=(s))
#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(),(x).end()
#define fi first
#define se second
#define M_PI           3.14159265358979323846

const int INF = 1e9 + 23;
const lolo MOD = 1e9 + 7;
const int N = 1e5 + 10;

vector<pii > gr[N];
lolo dist[N];
set<pii > blocks[N];
int n, m;

lolo getDepart(lolo v, lolo in) {
  auto it = blocks[v].upper_bound({in, INF});
  --it;
  pair<lolo, lolo> span = *it;
  lolo out = in;
  if (span.fi <= in) out = max(in, span.se);
  trace(v) trace(in) trace(out) trnl
  return out;
}

void dijkstra(int s) {
  fill(dist, dist + n, INF * 1LL * INF);
  typedef pair<lolo, lolo> qel;
  priority_queue<qel, vector<qel>, greater<qel> > q;
  q.push({0, s});
  while (!q.empty()) {
    qel el = q.top(); q.pop();
    lolo d = el.fi, u = el.se;
    if (dist[u] < d) continue;
    trace(u) trace(d) trnl
    dist[u] = d;
    lolo depart = getDepart(u, d);
    for (auto& it : gr[u]) {
      int e = it.fi, v = it.se;
      q.push({depart + e, v});
    }
  }
}

void read() {
  cin >> n >> m;
  int a, b, w;
  R(_, m) {
    cin >> a >> b >> w;
    --a, --b;
    gr[a].emplace_back(w, b);
    gr[b].emplace_back(w, a);
  }
  int arrives[N];
  R(i, n) {
    int k; cin >> k;
    R(j, k) cin >> arrives[j];
    if (k == 0 || arrives[0] > 0) {
      blocks[i].insert({0, 0});
    }
    for (int st = 0, en; st < k; st = en+1) {
      en = st;
      while (en+1 < k && arrives[en]+1 == arrives[en+1]) ++en;
      blocks[i].insert({arrives[st], arrives[en]+1});
    }
  }
}

int main()
{
  ios_base::sync_with_stdio(0);
  read();
  dijkstra(0);
  lolo ans = (dist[n-1] != INF * 1LL * INF ? dist[n-1] : -1);
  cout << ans << "\n";
  return 0;
}
// g++ -W -Wall -Wextra -pedantic -std=c++0x -o p main.cpp


#include <bits/stdc++.h>
using namespace std;

#ifdef LOCAL_CHECK
#define trace(x) cerr << #x << ": " << x << " ";
#define trnl cerr << "\n";
#else
#define trace(x) {}
#define trnl {}
#endif
typedef long long lolo;
typedef unsigned long long ulolo;
typedef pair<int, int> pii;
#define R(i,n) for(int i=0;i<(n);++i)
#define F(i,a,b) for(int i=(a);i<(b);++i)
#define FS(i,a,b,s) for(int i=(a);i<(b);i+=(s))
#define FD(i,n) for(int i=(n-1);i>=0;--i)
#define FDS(i,n,s) for(int i=(n-1);i>=0;i-=(s))
#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(),(x).end()
#define fi first
#define se second
#define M_PI           3.14159265358979323846

const int INF = 1e9 + 23;
const lolo MOD = 1e9 + 7;
const int N = 1e5 + 10;

vector<pii > gr[N];
lolo dist[N];
set<pii > blocks[N];
int n, m;

lolo getDepart(lolo v, lolo in) {
  auto it = blocks[v].upper_bound({in, INF});
  --it;
  pair<lolo, lolo> span = *it;
  lolo out = in;
  if (span.fi <= in) out = max(in, span.se);
  trace(v) trace(in) trace(out) trnl
  return out;
}

void dijkstra(int s) {
  fill(dist, dist + n, INF * 1LL * INF);
  typedef pair<lolo, lolo> qel;
  priority_queue<qel, vector<qel>, greater<qel> > q;
  q.push({0, s});
  while (!q.empty()) {
    qel el = q.top(); q.pop();
    lolo d = el.fi, u = el.se;
    if (dist[u] < d) continue;
    trace(u) trace(d) trnl
    dist[u] = d;
    lolo depart = getDepart(u, d);
    for (auto& it : gr[u]) {
      int e = it.fi, v = it.se;
      q.push({depart + e, v});
    }
  }
}

void read() {
  cin >> n >> m;
  int a, b, w;
  R(_, m) {
    cin >> a >> b >> w;
    --a, --b;
    gr[a].emplace_back(w, b);
    gr[b].emplace_back(w, a);
  }
  int arrives[N];
  R(i, n) {
    int k; cin >> k;
    R(j, k) cin >> arrives[j];
    if (k == 0 || arrives[0] > 0) {
      blocks[i].insert({0, 0});
    }
    for (int st = 0, en; st < k; st = en+1) {
      en = st;
      while (en+1 < k && arrives[en]+1 == arrives[en+1]) ++en;
      blocks[i].insert({arrives[st], arrives[en]+1});
    }
    if (k > 0) {
      blocks[i].insert({arrives[k-1]+1, arrives[k-1]+1});
    }
  }
}

int main()
{
  ios_base::sync_with_stdio(0);
  read();
  dijkstra(0);
  lolo ans = (dist[n-1] != INF * 1LL * INF ? dist[n-1] : -1);
  cout << ans << "\n";
  return 0;
}
// g++ -W -Wall -Wextra -pedantic -std=c++0x -o p main.cpp


#include <bits/stdc++.h>
using namespace std;

#ifdef LOCAL_CHECK
#define trace(x) cerr << #x << ": " << x << " ";
#define trnl cerr << "\n";
#else
#define trace(x) {}
#define trnl {}
#endif
typedef long long lolo;
typedef unsigned long long ulolo;
typedef pair<int, int> pii;
#define R(i,n) for(int i=0;i<(n);++i)
#define F(i,a,b) for(int i=(a);i<(b);++i)
#define FS(i,a,b,s) for(int i=(a);i<(b);i+=(s))
#define FD(i,n) for(int i=(n-1);i>=0;--i)
#define FDS(i,n,s) for(int i=(n-1);i>=0;i-=(s))
#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(),(x).end()
#define fi first
#define se second
#define M_PI           3.14159265358979323846

const int INF = 2e9 + 23;
const lolo MOD = 1e9 + 7;
const int N = 1e5 + 10;

vector<pii > gr[N];
int dist[N];
set<pii > blocks[N];
int n, m;

int getDepart(int v, int in) {
  auto it = blocks[v].upper_bound({in, INF});
  --it;
  pii span = *it;
  int out = in;
  if (span.fi <= in) out = max(in, span.se);
  return out;
}

void dijkstra(int s) {
  fill(dist, dist + n, INF);
  typedef pii qel;
  priority_queue<qel, vector<qel>, greater<qel> > q;
  q.push({0, s});
  while (!q.empty()) {
    qel el = q.top(); q.pop();
    int d = el.fi, u = el.se;
    if (dist[u] < d) continue;
    dist[u] = d;
    int depart = getDepart(u, d);
    for (auto& it : gr[u]) {
      int e = it.fi, v = it.se;
      q.push({depart + e, v});
    }
  }
}

void read() {
  cin >> n >> m;
  int a, b, w;
  R(_, m) {
    cin >> a >> b >> w;
    --a, --b;
    gr[a].emplace_back(w, b);
    gr[b].emplace_back(w, a);
  }
  int arrives[N];
  R(i, n) {
    int k; cin >> k;
    R(j, k) cin >> arrives[j];
    if (k == 0 || arrives[0] > 0) {
      blocks[i].insert({0, 0});
    }
    for (int st = 0, en; st < k; st = en+1) {
      en = st;
      while (en+1 < k && arrives[en]+1 == arrives[en+1]) ++en;
      blocks[i].insert({arrives[st], arrives[en]+1});
    }
  }
}

int main()
{
  ios_base::sync_with_stdio(0);
  read();
  dijkstra(0);
  int ans = (dist[n-1] != INF ? dist[n-1] : -1);
  cout << ans << "\n";
  return 0;
}
// g++ -W -Wall -Wextra -pedantic -std=c++0x -o p main.cpp


#include <bits/stdc++.h>
using namespace std;

#ifdef LOCAL_CHECK
#define trace(x) cerr << #x << ": " << x << " ";
#define trnl cerr << "\n";
#else
#define trace(x) {}
#define trnl {}
#endif
typedef long long lolo;
typedef unsigned long long ulolo;
typedef pair<int, int> pii;
#define R(i,n) for(int i=0;i<(n);++i)
#define F(i,a,b) for(int i=(a);i<(b);++i)
#define FS(i,a,b,s) for(int i=(a);i<(b);i+=(s))
#define FD(i,n) for(int i=(n-1);i>=0;--i)
#define FDS(i,n,s) for(int i=(n-1);i>=0;i-=(s))
#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(),(x).end()
#define fi first
#define se second
#define M_PI           3.14159265358979323846

const int INF = 1e9 + 23;
const lolo MOD = 1e9 + 7;
const int N = 1e5 + 10;

vector<pii > gr[N];
lolo dist[N];
set<pii > blocks[N];
int n, m;

lolo getDepart(lolo v, lolo in) {
  auto it = blocks[v].upper_bound({in, INF});
  --it;
  pair<lolo, lolo> span = *it;
  lolo out = in;
  if (span.fi <= in) out = max(in, span.se);
  return out;
}

void dijkstra(int s) {
  fill(dist, dist + n, INF * 1LL * INF);
  typedef pair<lolo, lolo> qel;
  priority_queue<qel, vector<qel>, greater<qel> > q;
  q.push({0, s});
  while (!q.empty()) {
    qel el = q.top(); q.pop();
    lolo d = el.fi, u = el.se;
    if (dist[u] < d) continue;
    dist[u] = d;
    lolo depart = getDepart(u, d);
    for (auto& it : gr[u]) {
      int e = it.fi, v = it.se;
      q.push({depart + e, v});
    }
  }
}

void read() {
  cin >> n >> m;
  int a, b, w;
  R(_, m) {
    cin >> a >> b >> w;
    --a, --b;
    gr[a].emplace_back(w, b);
    gr[b].emplace_back(w, a);
  }
  int arrives[N];
  R(i, n) {
    int k; cin >> k;
    R(j, k) cin >> arrives[j];
    if (k == 0 || arrives[0] > 0) {
      blocks[i].insert({0, 0});
    }
    for (int st = 0, en; st < k; st = en+1) {
      en = st;
      while (en+1 < k && arrives[en]+1 == arrives[en+1]) ++en;
      blocks[i].insert({arrives[st], arrives[en]+1});
    }
  }
}

int main()
{
  ios_base::sync_with_stdio(0);
  read();
  dijkstra(0);
  lolo ans = (dist[n-1] != INF * 1LL * INF ? dist[n-1] : -1);
  cout << ans << "\n";
  return 0;
}
// g++ -W -Wall -Wextra -pedantic -std=c++0x -o p main.cpp


#include <bits/stdc++.h>
#define f first
#define s second
#define pb push_back
using namespace std;
int n,m;
vector<int> vs[100005];
vector<int> gaps[100005];

vector<pair<int,int> > gs[100005];

int findbest(int x,int t){
    int l = 0,h = vs[x].size(),m;
    int ret = 1<<30;
    if(vs[x][l] > t || vs[x][h-1] < t)
            return 0;

    while(h-l > 1){
        m = (l+h)/2;
        cout<<l<<" "<<h<<" "<<m<<" "<<vs[x][m]<<" "<<ret<<endl;
        if(vs[x][m] <= t){
        //  l = m;
            int y = (m+h)/2;
            if(vs[x][y] < t) l = m;
            else h = m;
        }
        else{
        int y = (m+l)/2;
    if(vs[x][y] > t){
        h = m;
            }else l = m;
        }

    if(vs[x][m] > t && vs[x][m-1] < t) return t;

    if(vs[x][m] > t && vs[x][m] - 1!= vs[x][m-1])
        ret = min(vs[x][m] - 1,ret),cout<<"***"<<ret<<endl;

    if(vs[x][m] <= t && vs[x][m] + 1!= vs[x][m+1] && vs[x][m] + 1 > t)
        ret = min(vs[x][m] + 1,ret);
    }
cout<<"***"<<l<<" "<<h<<" "<<m<<" "<<vs[x][m]<<endl;
    return ret != 1<<30? ret : vs[x][vs[x].size()-1] + 1;
}

priority_queue<pair<int,int> , vector<pair<int,int> > ,greater<pair<int,int> > >q;
pair<int,pair<int,int> > pss;
int d[100005];
void dij(){
pair<int,int> p,ps,pr;
p = {0,1};
d[1] = 0;
q.push(p);

while(!q.empty()){
pr = q.top();q.pop();
int x = pr.f;
int xs = x;
if(vs[pr.s].size()){
int z = lower_bound(vs[pr.s].begin(),vs[pr.s].end(),x)-vs[pr.s].begin();
    xs = vs[pr.s][z];
if(xs > x) xs = x;
else if(xs == x){
        xs = gaps[pr.s][lower_bound(gaps[pr.s].begin(),gaps[pr.s].end(),x)-gaps[pr.s].begin()];
//  cout<<pr.s<<"*********.."<<xs<<endl;
    }
}
    if(xs < x) xs = x;
//cout<<pr.s<<" "<<xs<<endl;
 if(pr.s == n) return ;
if(d[pr.s] != pr.f) continue;
for(int i = 0;i < gs[pr.s].size();i++){
    p = gs[pr.s][i];
    int cost = xs + p.s;//lower_bound(vs[p.f].begin(),vs[p.f].end(),d[pr.s] + p.s);

 // cout<<xs<<" "<<p.s<<" "<<p.f<<" "<<d[p.f]<<endl;

    if(d[p.f] > cost){
        d[p.f] = cost;
        ps = {cost,p.f};
        q.push(ps);
//  cout<<"***"<<p.f<<" "<<xs<<endl;

    }

}

}

}

int main(){
    //freopen("in.txt","r",stdin);
    cin >> n >> m;
    int x,y,z;
    pair<int,int>p;

    for(int i = 0;i < m ;i++){
        cin >> x >> y >> z;
        p = {y,z};
        gs[x].pb(p);
        p = {x,z};
        gs[y].pb(p);
    }
for(int i = 1;i <= n ;i++){
    d[i] = 1<<30;
    cin >> x;
    if(x){
        cin >> y;//y++;
        vs[i].pb(y);
        for(int j = 1; j < x;j++){
            cin >> z;//z++;
            if(y+1 != z)
            gaps[i].pb(y+1);
            y = z;
            vs[i].pb(z);
        }
        gaps[i].pb(y+1);
        //cout<<endl;
    }
}
        dij();
        cout<<(d[n] == 1<<30 ? -1:d[n])<<endl;
    return 0;
}


#include <bits/stdc++.h>
#define FOR(i,n) for (int i=0;i<n;++i)
#define REP(i,a,b) for (int i=a;i<=b;++i)
#define REPD(i,a,b) for (int i=a;i>=b;--i)
#define pb push_back
#define X first
#define Y second
using namespace std;
typedef long long ll;
typedef pair<int,int> ii;
priority_queue<ii,vector<ii>,greater<ii> > Q;
const int N = 100010;
int n, m, d[N], nn[N];
vector<ii> ke[N]; vector<int> b[N];
void enter() {
    scanf("%d%d",&n,&m);
    int u, v, w;
    FOR(_,m) {
        scanf("%d%d%d",&u,&v,&w);
        ke[u].pb(ii(v,w)); ke[v].pb(ii(u,w));
    }
    REP(i,1,n) {
        scanf("%d",&nn[i]); b[i].resize(nn[i]);
        FOR(j,nn[i]) scanf("%d",&b[i][j]);
    }
}
bool Find(int i,int x) {
    if (nn[i] == 0) return false;
    int l = 0, r = nn[i] - 1, m = (l+r)>>1;
    while (l!=m && r!=m) {
        if (b[i][m] == x) return true;
        if (b[i][m] < x) l = m+1;
        else r = m-1;
        m = (l+r)>>1;
    }
    REP(m,l,r) if (b[i][m] == x) return true;
    return false;
}
void process() {
    REP(i,1,n) d[i] = 2e9;
    d[1] = 0; Q.push(ii(0,1));
    int u, v, w, c, t;
    while (!Q.empty()) {
        u = Q.top().Y; w = Q.top().X; Q.pop();
        if (w != d[u]) continue;
        while (Find(u,w)) w++;
        for (vector<ii>::iterator i=ke[u].begin();i!=ke[u].end();++i) {
            v = i->X; c = i->Y;
            if (w+c < d[v]) {
                d[v] = w+c; Q.push(ii(d[v],v));
            }
        }
    }
    if (d[n] == 2e9) cout << -1;
    else cout << d[n];
}
int main()
{
    enter();
    process();
    return 0;
}


#include <bits/stdc++.h>
#define FOR(i,n) for (int i=0;i<n;++i)
#define REP(i,a,b) for (int i=a;i<=b;++i)
#define REPD(i,a,b) for (int i=a;i>=b;--i)
#define pb push_back
#define X first
#define Y second
using namespace std;
typedef long long ll;
typedef pair<int,int> ii;
priority_queue<ii,vector<ii>,greater<ii> > Q;
const int N = 100010;
int n, m, d[N];;
vector<ii> ke[N]; set<int> s[N];
void enter() {
    scanf("%d%d",&n,&m);
    int u, v, w;
    FOR(_,m) {
        scanf("%d%d%d",&u,&v,&w);
        ke[u].pb(ii(v,w)); ke[v].pb(ii(u,w));
    }
    REP(i,1,n) {
        scanf("%d",&u);
        FOR(_,u) scanf("%d",&v), s[i].insert(v);
    }
}
void process() {
    REP(i,1,n) d[i] = 2e9;
    d[1] = 0; Q.push(ii(0,1));
    int u, v, w, c, t;
    while (!Q.empty()) {
        u = Q.top().Y; w = Q.top().X; Q.pop();
        if (w != d[u]) continue;
        for (vector<ii>::iterator i=ke[u].begin();i!=ke[u].end();++i) {
            v = i->X; c = i->Y; t = w;
            while (s[u].find(t) != s[u].end()) t++;
            if (t+c < d[v]) {
                d[v] = t+c; Q.push(ii(d[v],v));
            }
        }
    }
    if (d[n] == 2e9) cout << -1;
    else cout << d[n];
}
int main()
{
    enter();
    process();
    return 0;
}


#include <bits/stdc++.h>
#define FOR(i,n) for (int i=0;i<n;++i)
#define REP(i,a,b) for (int i=a;i<=b;++i)
#define REPD(i,a,b) for (int i=a;i>=b;--i)
#define pb push_back
#define X first
#define Y second
using namespace std;
typedef long long ll;
typedef pair<int,int> ii;
//typedef pair<ll,int> li;
priority_queue<ii,vector<ii>,greater<ii> > Q;
const int N = 100010;
int n, m;
vector<ii> ke[N]; set<int> s[N];
ll d[N];
void enter() {
    scanf("%d%d",&n,&m);
    int u, v, w;
    FOR(_,m) {
        scanf("%d%d%d",&u,&v,&w);
        ke[u].pb(ii(v,w)); ke[v].pb(ii(u,w));
    }
    REP(i,1,n) {
        scanf("%d",&u);
        FOR(_,u) scanf("%d",&v), s[i].insert(v);
    }
}
void process() {
    REP(i,1,n) d[i] = 2e9;
    d[1] = 0; Q.push(ii(0,1));
    int u, v, w, c, t;
    while (!Q.empty()) {
        u = Q.top().Y; w = Q.top().X; Q.pop();
        if (w != d[u]) continue;
        for (vector<ii>::iterator i=ke[u].begin();i!=ke[u].end();++i) {
            v = i->X; c = i->Y; t = w;
            while (s[u].count(t) > 0) t++;
            if (t+c < d[v]) {
                d[v] = t+c; Q.push(ii(d[v],v));
            }
        }
    }
    if (d[n] == 2e9) cout << -1;
    else cout << d[n];
}
int main()
{
    enter();
    process();
    return 0;
}


#include <bits/stdc++.h>
#define FOR(i,n) for (int i=0;i<n;++i)
#define REP(i,a,b) for (int i=a;i<=b;++i)
#define REPD(i,a,b) for (int i=a;i>=b;--i)
#define pb push_back
#define X first
#define Y second
using namespace std;
typedef long long ll;
typedef pair<int,int> ii;
priority_queue<ii,vector<ii>,greater<ii> > Q;
const int N = 100010;
int n, m, d[N], nn[N];
vector<ii> ke[N]; vector<int> b[N];
void enter() {
    scanf("%d%d",&n,&m);
    int u, v, w;
    FOR(_,m) {
        scanf("%d%d%d",&u,&v,&w);
        ke[u].pb(ii(v,w)); ke[v].pb(ii(u,w));
    }
    REP(i,1,n) {
        scanf("%d",&nn[i]); b[i].resize(nn[i]);
        FOR(j,nn[i]) scanf("%d",&b[i][j]);
    }
}
bool Find(int i,int x) {
    if (nn[i] == 0) return false;
    int l = 0, r = nn[i] - 1, m = (l+r)>>1;
    while (l!=m && r!=m) {
        if (b[i][m] == x) return true;
        if (b[i][m] < x) l = m+1;
        else r = m-1;
        m = (l+r)>>1;
    }
    REP(m,l,r) if (b[i][m] == x) return true;
    return false;
}
void process() {
    REP(i,1,n) d[i] = 2e9;
    d[1] = 0; Q.push(ii(0,1));
    int u, v, w, c, t;
    while (!Q.empty()) {
        u = Q.top().Y; w = Q.top().X; Q.pop();
        if (w != d[u]) continue;
        for (vector<ii>::iterator i=ke[u].begin();i!=ke[u].end();++i) {
            v = i->X; c = i->Y; t = w;
            while (Find(u,t)) t++;
            if (t+c < d[v]) {
                d[v] = t+c; Q.push(ii(d[v],v));
            }
        }
    }
    if (d[n] == 2e9) cout << -1;
    else cout << d[n];
}
int main()
{
    enter();
    process();
    return 0;
}


//lxrtxdy!
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

int n,m;
int k;
const int N = 1e5 + 10;

vector<pair<int,int>>edge[N];
vector<int>v[N];

long long dist[N];
bool st[N];

void spfa()
{
    memset(dist,0x3f,sizeof dist);
    dist[1] = 0;
    queue<int>q;
    q.push(1);

    while(q.size())
    {
        int t = q.front();
        q.pop();
        st[t] = false;

        int d = dist[t];

        for(auto &x : v[t])
        {
            if(x == d)
            {
                d = x + 1;
            }
        }

        for(auto &x : edge[t])
        {
            int ver = x.first,dis = x.second;

            if(dist[ver] > d + dis)
            {
                dist[ver] = d + dis;

                if(!st[ver])
                {
                    q.push(ver);
                    st[ver] = true;
                }
            }
        }
    }

}

int main()
{
    scanf("%d%d",&n,&m);

    for(int i = 0;i < m;i ++)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        edge[a].push_back({b,c});
        edge[b].push_back({a,c});
    }

    for(int i = 1;i <= n;i ++)
    {
        cin >> k;
        for(int j = 0;j < k;j ++)
        {
            int x;
            cin >> x;
            v[i].push_back(x);
        }
    }

    spfa();
    if(dist[n] >= 0x3f3f3f3f)cout << -1 << endl;
    else
    cout << dist[n] << endl;

    return 0;
}

//orzlxr!//hello


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<set>
#include<queue>
#define N 1000005
#define INF 10000000000007
#define M 1000005
#define LL long long
using namespace std;
LL nex[M],list[M],cost[M],head[N],cnt,dist[N],n,m,vis[N];
set<int>guest[N];
LL read()
{
    LL f=1,x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    return x*=f;
}
void insert(LL x,LL y,LL z)
{
	nex[++cnt]=head[x];
	list[cnt]=y;
	cost[cnt]=z;
	head[x]=cnt;
}
priority_queue<pair<int,int> >q;
LL solve(LL distance,LL cur)
{
	while(guest[cur].find(distance)!=guest[cur].end())
	{
		distance++;
	}
	return distance;
}
void dij(LL start)
{
	for(LL i=1;i<=n;i++)
	{
		dist[i]=INF;
	}
	dist[start]=0;
//	vis[start]=1;
	q.push(make_pair(0,start));
	while(!q.empty())
	{
		LL cur=q.top().second;
		LL distance=solve(q.top().first,q.top().second);

//		printf("cur=%d distance=%d\n",cur,distance);

		q.pop();

		if(!vis[cur])
		{
			vis[cur]=1;
			for(LL i=head[cur];i;i=nex[i])
			{
				LL k=list[i];
				if(dist[k]>distance+cost[i])
				{
					dist[k]=distance+cost[i];
					q.push(make_pair(dist[k],k));
				}
			}
		}
	}
}
int main()
{
	cin>>n>>m;
	for(LL i=1;i<=m;i++)
	{
		LL x,y,z;
		x=read();y=read();z=read();
//		cin>>x>>y>>z;
		insert(x,y,z);
		insert(y,x,z);
	}
	for(LL i=1;i<=n;i++)
	{
		LL k;
		k=read();
		for(LL j=1;j<=k;j++)
		{
			LL tmp;
			tmp=read();
			guest[i].insert(tmp);
		}
	}
	dij(1);
	cout<<((vis[n])?(dist[n]):(-1))<<endl;
//	for(LL i=1;i<=n;i++)
//	{
//		printf("dist[%I64d]=%I64d\n",i,dist[i]);
//	}
	return 0;
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<set>
#include<queue>
#define N 1000005
#define INF 1000000000000007
#define M 1000005
#define LL long long
using namespace std;
LL nex[M],list[M],cost[M],head[N],cnt,dist[N],n,m,vis[N];
set<int>guest[N];
LL read()
{
    LL f=1,x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    return x*=f;
}
void insert(LL x,LL y,LL z)
{
	nex[++cnt]=head[x];
	list[cnt]=y;
	cost[cnt]=z;
	head[x]=cnt;
}
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
LL solve(LL distance,LL cur)
{
	while(guest[cur].find(distance)!=guest[cur].end())
	{
		distance++;
	}
	return distance;
}
void dij(LL start)
{
	for(LL i=1;i<=n;i++)
	{
		dist[i]=INF;
	}
	dist[start]=0;
//	vis[start]=1;
	q.push(make_pair(0,start));
	while(!q.empty())
	{
		LL cur=q.top().second;
		LL distance=solve(q.top().first,q.top().second);

//		printf("cur=%d distance=%d\n",cur,distance);

		q.pop();

		if(!vis[cur])
		{
			vis[cur]=1;
			for(LL i=head[cur];i;i=nex[i])
			{
				LL k=list[i];
				if(dist[k]>distance+cost[i])
				{
					dist[k]=distance+cost[i];
					q.push(make_pair(dist[k],k));
				}
			}
		}
	}
}
int main()
{
	cin>>n>>m;
	for(LL i=1;i<=m;i++)
	{
		LL x,y,z;
		x=read();y=read();z=read();
//		cin>>x>>y>>z;
		insert(x,y,z);
		insert(y,x,z);
	}
	for(LL i=1;i<=n;i++)
	{
		LL k;
		k=read();
		for(LL j=1;j<=k;j++)
		{
			LL tmp;
			tmp=read();
			guest[i].insert(tmp);
		}
	}
	dij(1);
	cout<<((vis[n])?(dist[n]):(-1))<<endl;
//	for(LL i=1;i<=n;i++)
//	{
//		printf("dist[%I64d]=%I64d\n",i,dist[i]);
//	}
	return 0;
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<set>
#include<queue>
#define N 200005
#define INF 10000000000007
#define M 300005
#define LL long long
using namespace std;
LL nex[M],list[M],cost[M],head[N],cnt,dist[N],n,m,vis[N];
set<int>guest[N];
LL read()
{
    LL f=1,x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    return x*=f;
}
void insert(LL x,LL y,LL z)
{
	nex[++cnt]=head[x];
	list[cnt]=y;
	cost[cnt]=z;
	head[x]=cnt;
}
priority_queue<pair<int,int> >q;
LL solve(LL distance,LL cur)
{
	while(guest[cur].find(distance)!=guest[cur].end())
	{
		distance++;
	}
	return distance;
}
void dij(LL start)
{
	for(LL i=1;i<=n;i++)
	{
		dist[i]=INF;
	}
	dist[start]=0;
//	vis[start]=1;
	q.push(make_pair(0,start));
	while(!q.empty())
	{
		LL cur=q.top().second;
		LL distance=solve(q.top().first,q.top().second);

//		printf("cur=%d distance=%d\n",cur,distance);

		q.pop();

		if(!vis[cur])
		{
			vis[cur]=1;
			for(LL i=head[cur];i;i=nex[i])
			{
				LL k=list[i];
				if(dist[k]>distance+cost[i])
				{
					dist[k]=distance+cost[i];
					q.push(make_pair(dist[k],k));
				}
			}
		}
	}
}
int main()
{
	cin>>n>>m;
	for(LL i=1;i<=m;i++)
	{
		LL x,y,z;
		x=read();y=read();z=read();
//		cin>>x>>y>>z;
		insert(x,y,z);
		insert(y,x,z);
	}
	for(LL i=1;i<=n;i++)
	{
		LL k;
		k=read();
		for(LL j=1;j<=k;j++)
		{
			LL tmp;
			tmp=read();
			guest[i].insert(tmp);
		}
	}
	dij(1);
	cout<<((vis[n])?(dist[n]):(-1))<<endl;
//	for(LL i=1;i<=n;i++)
//	{
//		printf("dist[%I64d]=%I64d\n",i,dist[i]);
//	}
	return 0;
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<set>
#include<queue>
#define N 1000005
#define INF 1000000000000007
#define M 1000005
#define LL long long
using namespace std;
LL nex[M],list[M],cost[M],head[N],cnt,dist[N],n,m,vis[N];
set<int>guest[N];
LL read()
{
    LL f=1,x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    return x*=f;
}
void insert(LL x,LL y,LL z)
{
	nex[++cnt]=head[x];
	list[cnt]=y;
	cost[cnt]=z;
	head[x]=cnt;
}
priority_queue<pair<int,int> >q;
LL solve(LL distance,LL cur)
{
	while(guest[cur].find(distance)!=guest[cur].end())
	{
		distance++;
	}
	return distance;
}
void dij(LL start)
{
	for(LL i=1;i<=n;i++)
	{
		dist[i]=INF;
	}
	dist[start]=0;
//	vis[start]=1;
	q.push(make_pair(0,start));
	while(!q.empty())
	{
		LL cur=q.top().second;
		LL distance=solve(q.top().first,q.top().second);

//		printf("cur=%d distance=%d\n",cur,distance);

		q.pop();

		if(!vis[cur])
		{
			vis[cur]=1;
			for(LL i=head[cur];i;i=nex[i])
			{
				LL k=list[i];
				if(dist[k]>distance+cost[i])
				{
					dist[k]=distance+cost[i];
					q.push(make_pair(dist[k],k));
				}
			}
		}
	}
}
int main()
{
	cin>>n>>m;
	for(LL i=1;i<=m;i++)
	{
		LL x,y,z;
		x=read();y=read();z=read();
//		cin>>x>>y>>z;
		insert(x,y,z);
		insert(y,x,z);
	}
	for(LL i=1;i<=n;i++)
	{
		LL k;
		k=read();
		for(LL j=1;j<=k;j++)
		{
			LL tmp;
			tmp=read();
			guest[i].insert(tmp);
		}
	}
	dij(1);
	cout<<((vis[n])?(dist[n]):(-1))<<endl;
//	for(LL i=1;i<=n;i++)
//	{
//		printf("dist[%I64d]=%I64d\n",i,dist[i]);
//	}
	return 0;
}


#include<iostream>
#include<cstring>
#include<queue>
#include<set>
using namespace std;
const int maxn=1e6+9;
int head[maxn],dis[maxn],book[maxn],n,m,cnt;
set<int > s[maxn];
struct node{
	int id;
	int val;
	int next;
}side[maxn];
void init()
{
	memset(head,-1,sizeof(head));
	memset(dis,0x3f3f3f3f,sizeof(dis));
	memset(book,0,sizeof(book));
	cnt=0;
}
void add(int x,int y,int d)
{
	side[cnt].id=y;
	side[cnt].val=d;
	side[cnt].next=head[x];
	head[x]=cnt++;
}
int solve(int num,int id)
{
	while(s[id].find(num)!=s[id].end())
	{
		num++;
	}
	return num;
}
void spfa(int sx)
{
	queue<int> q;
	dis[sx]=0;book[sx]=1;
	q.push(sx);
	while(q.size())
	{
		int x=q.front();
		book[x]=0;
		q.pop();
		int tmp=solve(dis[x],x);
		for(int i=head[x];i!=-1;i=side[i].next)
		{
			int y=side[i].id;
			if(dis[y]>tmp+side[i].val)
			{
				dis[y]=tmp+side[i].val;
				if(!book[y])
				{
					book[y]=1;
					q.push(y);
				}
			}
		}
	}
}
int main()
{
	int a,b,c,k;
	cin>>n>>m;
	init();
	for(int i=1;i<=m;i++)
	{
		cin>>a>>b>>c;
		add(a,b,c);
		add(b,a,c);
	}
	for(int i=1;i<=n;i++)
	{
		cin>>a;
		for(int j=1;j<=a;j++)
		{
			cin>>b;
			s[i].insert(b);
		}
	}
	spfa(1);
	if(dis[n]==0x3f3f3f3f)
        cout<<-1<<endl;
    else
        cout<<dis[n]<<endl;
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

using ll = long long;
const int sz = 1e5 + 10;
const ll inf = 1e18;

int n, m;

vector < int > G[sz], W[sz], T[sz], B[sz];
ll dis[sz];

void dijk() {
        memset(dis, 63, sizeof dis);
        auto cmp = [](int a, int b) { return dis[a] > dis[b];};
        priority_queue < int, vector < int >, decltype(cmp) > PQ(cmp);
        dis[1] = 0;
        PQ.push(1);
        while (!PQ.empty()) {
                int u = PQ.top(); PQ.pop();
                int len = G[u].size();
                for (int i = 0; i < len; i++) {
                        int v = G[u][i];
                        ll w = W[u][i];
                        ll ww = dis[u] + w;
                        if (binary_search(T[u].begin(), T[u].end(), dis[u])) {
                                ww = B[u][lower_bound(T[u].begin(), T[u].end(), dis[u]) - T[u].begin()] + w;
                        }
                        if (dis[v] > ww) {
                                dis[v] = ww;
                                PQ.push(v);
                        }
                }
        }
        if (dis[n] >= dis[0]) dis[n] = -1ll;
}

int main() {
#ifdef CLown1331
        freopen( "in.txt", "r", stdin );
#endif // CLown1331

        while (scanf("%d %d", &n, &m) == 2) {

                for (int i = 0; i <= n; i++) G[i].clear(), W[i].clear(), T[i].clear();

                while (m--) {
                        int x, y, w;
                        scanf("%d %d %d", &x, &y, &w);
                        G[x].push_back(y);
                        W[x].push_back(w);
                        G[y].push_back(x);
                        W[y].push_back(w);
                }

                for (int i = 1; i <= n; i++) {
                        int t;
                        scanf("%d", &t);
                        T[i].resize(t);
                        B[i].resize(t);
                        for (int &x: T[i]) {
                                scanf("%d", &x);
                        }
                        int pr = INT_MAX;
                        for (int j = t - 1; j >= 0; j--) {
                                if (T[i][j] + 1 == pr) {
                                        B[i][j] = B[i][j + 1];
                                } else {
                                        B[i][j] = T[i][j] + 1;
                                }
                                pr = T[i][j];
                        }
                }

                dijk();

                printf("%lld\n", dis[n]);

                cerr << "-----\n";
        }

        return 0;
}


#include <iostream>
#include <cstdio>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <queue>

  int n, m, u, v, k, t, x;
  std::vector <std::vector <std::pair <int, int> > > G(100001);
  std::set <int> st[100001];
  std::queue <int> q;
  bool vis[100001];
  long long prices[100001];

  void BFS(int time, int node)
  {
  	  int value;
  	  for (int i = 0; i < G[node].size(); i++)
  	  {
  	  	  value = prices[node] + G[node][i].second;
  		  while(st[G[node][i].first].find(value) != st[G[node][i].first].end() && G[node][i].first != n)
  		  {
  			  value++;
  		  }

  		  if (value < prices[G[node][i].first])
  		  {
  		  	  q.push(G[node][i].first);
		      prices[G[node][i].first] = value;
  		  }
  	  }
  }

int main()
{
	std::cin >> n >> m;
	for (int i = 1; i <= m; i++)
	{
		scanf ("%d %d %d", &u, &v, &t);
		G[u].push_back(std::make_pair(v, t));
		G[v].push_back(std::make_pair(u, t));
	}

	for (int i = 1; i <= n; i++)
	{
		scanf ("%d", &k);
		while (k--)
		{
			scanf ("%d", &x);
			st[i].insert(x);
		}
		prices[i] = 1000000000000000000;
	}
	prices[1] = 0;
	while(st[1].find(prices[1]) != st[1].end())
	{
		prices[1]++;
	}

	q.push(1);
	while (!q.empty())
	{
		int member = q.front();
		q.pop();
		BFS(prices[member], member);
	}

	if (prices[n] == 1000000000000000000)
		std::cout << -1;
	else
		std::cout << prices[n];

	return 0;
}


#include <iostream>
#include <cstdio>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <queue>

  int n, m, u, v, k, t, x;
  std::vector <std::vector <std::pair <int, int> > > G(100001);
  std::set <int> st[100001];
  std::queue <int> q;
  bool vis[100001];
  long long prices[100001];

  void BFS(int time, int node)
  {
  	  int value;
  	  for (int i = 0; i < G[node].size(); i++)
  	  {
  	  	  value = prices[node] + G[node][i].second;
  		  while(st[G[node][i].first].find(value) != st[G[node][i].first].end() && G[node][i].first != n)
  		  {
  			  value++;
  		  }

  		  if (value < prices[G[node][i].first])
  		  {
  		  	  q.push(G[node][i].first);
		      prices[G[node][i].first] = value;
  		  }
  	  }
  }

int main()
{
	std::cin >> n >> m;
	for (int i = 1; i <= m; i++)
	{
		scanf ("%d %d %d", &u, &v, &t);
		G[u].push_back(std::make_pair(v, t));
		G[v].push_back(std::make_pair(u, t));
	}

	for (int i = 1; i <= n; i++)
	{
		scanf ("%d", &k);
		while (k--)
		{
			scanf ("%d", &x);
			st[i].insert(x);
		}
		prices[i] = 1000000000000000000;
	}
	prices[1] = 0;

	q.push(1);
	while (!q.empty())
	{
		int member = q.front();
		q.pop();
		BFS(prices[member], member);
	}

	if (prices[n] == 1000000000000000000)
		std::cout << -1;
	else
		std::cout << prices[n];

	return 0;
}


#include <iostream>
#include <cstdio>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <queue>

  int n, m, u, v, k, t, x;
  std::vector <std::vector <std::pair <int, int> > > G(100001);
  std::set <int> st[100001];
  std::queue <int> q;
  bool vis[100001];
  long long prices[100001];

  void BFS(int time, int node)
  {
  	  int value;
  	  for (int i = 0; i < G[node].size(); i++)
  	  {
  	  	  value = prices[node] + G[node][i].second;
  		  while(st[G[node][i].first].find(value) != st[G[node][i].first].end())
  		  {
  			  value++;
  		  }

  		  if (value < prices[G[node][i].first])
  		  {
  		  	  q.push(G[node][i].first);
		      prices[G[node][i].first] = value;
  		  }
  	  }
  }

int main()
{
	std::cin >> n >> m;
	for (int i = 1; i <= m; i++)
	{
		scanf ("%d %d %d", &u, &v, &t);
		G[u].push_back(std::make_pair(v, t));
		G[v].push_back(std::make_pair(u, t));
	}

	for (int i = 1; i <= n; i++)
	{
		scanf ("%d", &k);
		while (k--)
		{
			scanf ("%d", &x);
			st[i].insert(x);
		}
		prices[i] = 1000000000000000000;
	}
	prices[1] = 0;

	q.push(1);
	while (!q.empty())
	{
		int member = q.front();
		q.pop();
		BFS(prices[member], member);
	}

	if (prices[n] == 1000000000000000000)
		std::cout << -1;
	else
		std::cout << prices[n];

	return 0;
}


#include <iostream>
#include <cstdio>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <queue>

  int n, m, u, v, k, t, x;
  std::vector <std::vector <std::pair <int, int> > > G(100001);
  std::set <int> st[100001];
  std::queue <int> q;
  bool vis[100001];
  long long prices[100001];

  void BFS(int time, int node)
  {
  	  int value;
  	  for (int i = 0; i < G[node].size(); i++)
  	  {
  	  	  value = prices[node] + G[node][i].second;
  		  while(st[G[node][i].first].find(value) != st[G[node][i].first].end())
  		  {
  			  value++;
  		  }

  		  if (value < prices[G[node][i].first])
  		  {
  		  	  q.push(G[node][i].first);
		      prices[G[node][i].first] = value;
  		  }
  	  }
  }

int main()
{
	std::cin >> n >> m;
	for (int i = 1; i <= m; i++)
	{
		scanf ("%d %d %d", &u, &v, &t);
		G[u].push_back(std::make_pair(v, t));
		G[v].push_back(std::make_pair(u, t));
	}
	prices[1] = 0;

	for (int i = 1; i <= n; i++)
	{
		scanf ("%d", &k);
		while (k--)
		{
			scanf ("%d", &x);
			st[i].insert(x);
		}
		prices[i] = 1000000000000000000;
	}

	q.push(1);
	while (!q.empty())
	{
		int member = q.front();
		q.pop();
		BFS(prices[member], member);
	}

	if (prices[n] == 1000000000000000000)
		std::cout << -1;
	else
		std::cout << prices[n];

	return 0;
}