import java.util.*;

public class LizardsAndBasements2 {

    static int N, a, b;
    static int[] h;
    static Integer[][][][] dp;
    static State[][][][] path;
    static final int INF = (int)1e9;

    static class State {
        int i, p, c, n;
        State(int i, int p, int c, int n) {
            this.i = i;
            this.p = p;
            this.c = c;
            this.n = n;
        }

        @Override
        public String toString() {
            return "(" + i + ", " + p + ", " + c + ", " + n + ")";
        }
    }

    static int solve(int index, int prev, int cur, int next) {
        prev = Math.max(0, prev);
        cur = Math.max(0, cur);
        next = Math.max(0, next);

        if (dp[index][prev][cur][next] != null) {
            return dp[index][prev][cur][next];
        }

        int ans = INF;
        if (index == N - 1) {
            return ans = prev + cur == 0 ? 0 : INF;
        } else if (index == N - 2) {
            if (next > 0) {
                ans = 1 + solve(index, prev - b, cur - a, next - b);
                path[index][prev][cur][next] = new State(index, prev - b, cur - a, next - b);
            } else {
                ans = prev + cur + next == 0 ? 0 : INF;
            }
        } else {
            if (prev > 0) {
                ans = 1 + solve(index, prev - b, cur - a, next - b);
                path[index][prev][cur][next] = new State(index, prev - b, cur - a, next - b);
            } else {
                if (cur > 0) {
                    ans = 1 + solve(index, prev - b, cur - a, next - b);
                    path[index][prev][cur][next] = new State(index, prev - b, cur - a, next - b);
                }
                int nn = index < N - 2 ? h[index + 2] : 0;
                int ans2 = solve(index + 1, cur, next, nn);
                if (ans2 < ans) {
                    ans = ans2;
                    path[index][prev][cur][next] = new State(index + 1, cur, next, nn);
                }
            }
        }
        return dp[index][prev][cur][next] = ans;
    }

    static void printPath() {
        State state = new State(1, h[0], h[1], h[2]);

        while (state != null) {
            if (Math.max(0, state.p) + Math.max(0, state.c) + Math.max(0, state.n) > 0)
                System.out.print((state.i + 1) + " ");
            state = path[state.i][Math.max(0, state.p)][Math.max(0, state.c)][Math.max(0, state.n)];
        }
        System.out.println();
    }

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

        N = in.nextInt();
        a = in.nextInt();
        b = in.nextInt();
        h = new int[N];
        for (int i = 0; i < N; i++) {
            h[i] = in.nextInt() + 1;
        }

        dp = new Integer[20][20][20][20];
        path = new State[20][20][20][20];
        int ans = solve(1, h[0], h[1], h[2]);
        System.out.println(ans);
        printPath();

        in.close();
        System.exit(0);
    }
}

This is simplified version of the problem used on the original contest. The original problem seems to have too difiicult solution. The constraints for input data have been reduced.Polycarp likes to play computer role-playing game «Lizards and Basements». At the moment he is playing it as a magician. At one of the last levels he has to fight the line of archers. The only spell with which he can damage them is a fire ball. If Polycarp hits the i-th archer with his fire ball (they are numbered from left to right), the archer loses a health points. At the same time the spell damages the archers adjacent to the i-th (if any) — they lose b (1 ≤ b < a ≤ 10) health points each.As the extreme archers (i.e. archers numbered 1 and n) are very far, the fire ball cannot reach them. Polycarp can hit any other archer with his fire ball.The amount of health points for each archer is known. An archer will be killed when this amount is less than 0. What is the minimum amount of spells Polycarp can use to kill all the enemies?Polycarp can throw his fire ball into an archer if the latter is already killed.

The first line of the input contains three integers n, a, b (3 ≤ n ≤ 10; 1 ≤ b < a ≤ 10). The second line contains a sequence of n integers — h1, h2, ..., hn (1 ≤ hi ≤ 15), where hi is the amount of health points the i-th archer has.

In the first line print t — the required minimum amount of fire balls. In the second line print t numbers — indexes of the archers that Polycarp should hit to kill all the archers in t shots. All these numbers should be between 2 and n - 1. Separate numbers with spaces. If there are several solutions, output any of them. Print numbers in any order.

import java.util.*;

public class LizardsAndBasements2 {

    static int N, a, b;
    static int[] h;
    static Integer[][][] dp;
    static int[][][] path;
    static final int INF = (int)1e9;

    static int solve(int index, int prev, int cur) {
        if (index == N - 1) {
            return prev == 0 && cur == 0 ? 0 : INF;
        }

        if (dp[index][prev][cur] != null) {
            return dp[index][prev][cur];
        }
        int ans = INF;
        int shots = 0;
        int next = h[index + 1];
        while (true) {
            if (prev - b * shots <= 0) {
                int tmp = shots + solve(index + 1, Math.max(0, cur - a * shots), Math.max(0, next - b * shots));
                if (tmp < ans) {
                    ans = tmp;
                    path[index][prev][cur] = shots;
                }

            }
            if (prev - b * shots <= 0 && cur - a * shots <= 0 && next - b * shots <= 0)
                break;
            shots++;
        }
        return dp[index][prev][cur] = ans;
    }

    static void printPath(int index, int prev, int cur) {
        if (index == N - 1) return;
        int shots = path[index][prev][cur];
        for (int i = 0; i < shots; i++) {
            System.out.print((index + 1) + " ");
        }
        int next = h[index + 1];
        printPath(index + 1, Math.max(0, cur - a * shots), Math.max(0, next - b * shots));
    }

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

        N = in.nextInt();
        a = in.nextInt();
        b = in.nextInt();
        h = new int[N];
        for (int i = 0; i < N; i++) {
            h[i] = in.nextInt() + 1;
        }

        dp = new Integer[20][20][20];
        path = new int[20][20][20];
        int ans = solve(1, h[0], h[1]);
        System.out.println(ans);
        printPath(1, h[0], h[1]);
        System.out.println();

        in.close();
        System.exit(0);
    }
}


import java.io.*;
import java.util.*;

public class D {
	String line = null;
	String error = "errtype";
	String voi = "void";
	public void run() throws Exception{

		BufferedReader br = null;
		File file = new File("input.txt");
		if(file.exists()){
			br = new BufferedReader(new FileReader("input.txt"));
		}
		else{
			br = new BufferedReader(new InputStreamReader(System.in));
		}

		line = br.readLine();
		int N = Integer.parseInt(line);

		int c = 0;
		List<Widgit> list = new ArrayList<Widgit>();

		while(c < N){
			line = br.readLine();
			String[] ls = line.split(" ");
			if(ls[0].equals("Widget")){
				String s = ls[1];
				int p1 = s.indexOf('(');
				int p2 = s.indexOf(',');
				int p3 = s.indexOf(')');
				String name = s.substring(0, p1);
				String xs = s.substring(p1+1, p2);
				String ys = s.substring(p2+1, p3);
				int x = Integer.parseInt(xs);
				int y = Integer.parseInt(ys);
				Widgit w = new Widgit(x, y);
				w.name = name;
				list.add(w);
			}
			else if(ls[0].equals("VBox")){
				String name = ls[1];
				VBox v = new VBox();
				v.name = name;
				list.add(v);
			}
			else if(ls[0].equals("HBox")){
				String name = ls[1];
				HBox v = new HBox();
				v.name = name;
				list.add(v);
			}
			else{
				String s = ls[0];
				if(s.contains(".pack(")){
					int p1 = s.indexOf('.');
					int p2 = s.indexOf('(');
					int p3 = s.indexOf(')');
					String parn = s.substring(0, p1);
					String chin = s.substring(p2+1, p3);

					Boxbase box = null;
					Widgit w = null;
					for(int i = 0; i < list.size(); i++){
						if(parn.equals(list.get(i).name)){
							box = (Boxbase)list.get(i);
						}
						else if(chin.equals(list.get(i).name)){
							w = list.get(i);
						}
					}
					if(w != null){
						box.pack(w);
					}
				}
				else if(s.contains(".set_border(")){
					int p1 = s.indexOf('.');
					int p2 = s.indexOf('(');
					int p3 = s.indexOf(')');
					String name = s.substring(0, p1);
					String atai = s.substring(p2+1, p3);
					int num = Integer.parseInt(atai);

					Boxbase box = null;
					for(int i = 0; i < list.size(); i++){
						if(name.equals(list.get(i).name)){
							box = (Boxbase)list.get(i);
						}

					}
					if(box != null){
						box.setBorder(num);
					}
				}
				else if(s.contains(".set_spacing(")){
					int p1 = s.indexOf('.');
					int p2 = s.indexOf('(');
					int p3 = s.indexOf(')');
					String name = s.substring(0, p1);
					String atai = s.substring(p2+1, p3);
					int num = Integer.parseInt(atai);

					Boxbase box = null;
					for(int i = 0; i < list.size(); i++){
						if(name.equals(list.get(i).name)){
							box = (Boxbase)list.get(i);
						}

					}
					if(box != null){
						box.setSpace(num);
					}
				}
			}

			c++;
		}
		List<String> namelist = new ArrayList<String>();
		for(int i = 0; i < list.size(); i++){
			namelist.add(list.get(i).name);
		}

		String[] slist = new String[0];
		slist = namelist.toArray(slist);
		Arrays.sort(slist);
		for(int i = 0; i < slist.length; i++){
			String name = slist[i];

			for(int j = 0; j < list.size(); j++){
				if(list.get(j).name.equals(name)){
					String size = list.get(j).getSize();
					System.out.println(name + " " + size);
					break;
				}
			}

		}

	}

	private class Widgit{
		public String name = "";

		public int getSizeX(){
			return x;
		}
		public int getSizeY(){
			return y;
		}

		public Widgit(){

		}

		public Widgit(int x, int y){
			this.x = x;
			this.y = y;
		}

		public String getSize(){
			String ans = x + " " + y;
			return ans;
		}

		int x = 0;
		int y = 0;
	}

	private class Boxbase extends Widgit{
		int bo = 0;
		int sp = 0;

		List<Widgit> list = new ArrayList<Widgit>();

		public void setBorder(int b){
			bo = b;
		}
		public void setSpace(int s){
			sp = s;
		}

		public void pack(Widgit w){
			list.add(w);
		}

		public Boxbase(){

		}
		public Boxbase(int x, int y){
			this.x = x;
			this.y = y;
		}
	}

	private class VBox extends Boxbase{
		public VBox(){

		}
		public VBox(int x, int y){
			this.x = x;
			this.y = y;
		}

		public int getSizeX(){
			if(list.size() == 0){
				return 0;
			}

			int x = 0;
			for(int i = 0; i < list.size(); i++){

				x = Math.max(x, list.get(i).getSizeX());
			}
			x+= 2* bo;

			return x;
		}
		public int getSizeY(){
			if(list.size() == 0){
				return 0;
			}
			int y = 0;

			for(int i = 0; i < list.size(); i++){
				y += list.get(i).getSizeY();
			}

			y += 2*bo;
			int spnum = list.size() - 1;
			y+=spnum * sp;
			return y;
		}

		public String getSize(){
			if(list.size() == 0){
				return "0 0";
			}
			int y = 0;
			int x = 0;
			for(int i = 0; i < list.size(); i++){
				y += list.get(i).getSizeY();
				x = Math.max(x, list.get(i).getSizeX());
			}
			x+= 2* bo;
			y += 2*bo;
			int spnum = list.size() - 1;
			y+=spnum * sp;
			String ans = x + " " + y;
			return ans;
		}

	}

	private class HBox extends Boxbase{
		public HBox(){

		}
		public HBox(int x, int y){
			this.x = x;
			this.y = y;
		}

		public int getSizeX(){
			if(list.size() == 0){
				return 0;
			}

			int x = 0;
			for(int i = 0; i < list.size(); i++){
				x += list.get(i).getSizeX();

			}
			x+= 2* bo;

			int spnum = list.size() - 1;
			x+=spnum * sp;
			return x;
		}
		public int getSizeY(){
			if(list.size() == 0){
				return 0;
			}
			int y = 0;

			for(int i = 0; i < list.size(); i++){

				y = Math.max(y, list.get(i).getSizeY());
			}

			y += 2*bo;

			return y;
		}

		public String getSize(){
			if(list.size() == 0){
				return "0 0";
			}
			int y = 0;
			int x = 0;
			for(int i = 0; i < list.size(); i++){
				x += list.get(i).getSizeX();
				y = Math.max(y, list.get(i).getSizeY());
			}
			x+= 2* bo;
			y += 2*bo;
			int spnum = list.size() - 1;
			x+=spnum * sp;
			String ans = x + " " + y;
			return ans;
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception{
		D t = new D();
		t.run();

	}

}

It is nighttime and Joe the Elusive got into the country's main bank's safe. The safe has n cells positioned in a row, each of them contains some amount of diamonds. Let's make the problem more comfortable to work with and mark the cells with positive numbers from 1 to n from the left to the right.Unfortunately, Joe didn't switch the last security system off. On the plus side, he knows the way it works.Every minute the security system calculates the total amount of diamonds for each two adjacent cells (for the cells between whose numbers difference equals 1). As a result of this check we get an n - 1 sums. If at least one of the sums differs from the corresponding sum received during the previous check, then the security system is triggered.Joe can move the diamonds from one cell to another between the security system's checks. He manages to move them no more than m times between two checks. One of the three following operations is regarded as moving a diamond: moving a diamond from any cell to any other one, moving a diamond from any cell to Joe's pocket, moving a diamond from Joe's pocket to any cell. Initially Joe's pocket is empty, and it can carry an unlimited amount of diamonds. It is considered that before all Joe's actions the system performs at least one check.In the morning the bank employees will come, which is why Joe has to leave the bank before that moment. Joe has only k minutes left before morning, and on each of these k minutes he can perform no more than m operations. All that remains in Joe's pocket, is considered his loot.Calculate the largest amount of diamonds Joe can carry with him. Don't forget that the security system shouldn't be triggered (even after Joe leaves the bank) and Joe should leave before morning.

The first line contains integers n, m and k (1 ≤ n ≤ 104, 1 ≤ m, k ≤ 109). The next line contains n numbers. The i-th number is equal to the amount of diamonds in the i-th cell — it is an integer from 0 to 105.

Print a single number — the maximum number of diamonds Joe can steal.

NoteIn the second sample Joe can act like this:The diamonds' initial positions are 4 1 3.During the first period of time Joe moves a diamond from the 1-th cell to the 2-th one and a diamond from the 3-th cell to his pocket.By the end of the first period the diamonds' positions are 3 2 2. The check finds no difference and the security system doesn't go off.During the second period Joe moves a diamond from the 3-rd cell to the 2-nd one and puts a diamond from the 1-st cell to his pocket.By the end of the second period the diamonds' positions are 2 3 1. The check finds no difference again and the security system doesn't go off.Now Joe leaves with 2 diamonds in his pocket.

import java.io.*;
import java.util.StringTokenizer;

public class Main {

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        PrintWriter out = new PrintWriter(System.out);
        int n = sc.nextInt();
        int m = sc.nextInt();
        int k = sc.nextInt();
        int[] a = sc.nextIntArray(n);
        if (n % 2 == 0) {
            System.out.println(0);
            return;
        }
        int min = (int) (1e5 + 10);
        for (int i = 0; i < n; i += 2)
            min = Math.min(min, a[i]);
        int y = n / 2 + 1;
        out.println(Math.min(min, 1l * k * (m / y)));
        out.flush();
        out.close();
    }

    static class Scanner {
        StringTokenizer st;
        BufferedReader br;

        public Scanner(InputStream system) {
            br = new BufferedReader(new InputStreamReader(system));
        }

        public String next() throws IOException {
            while (st == null || !st.hasMoreTokens()) st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        public String nextLine() throws IOException {
            return br.readLine();
        }

        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        public double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }

        public char nextChar() throws IOException {
            return next().charAt(0);
        }

        public Long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        public boolean ready() throws IOException {
            return br.ready();
        }

        public int[] nextIntArray(int n) throws IOException {
            int[] a = new int[n];
            for (int i = 0; i < n; i++)
                a[i] = nextInt();
            return a;
        }

        public long[] nextLongArray(int n) throws IOException {
            long[] a = new long[n];
            for (int i = 0; i < n; i++)
                a[i] = nextLong();
            return a;
        }

        public Integer[] nextIntegerArray(int n) throws IOException {
            Integer[] a = new Integer[n];
            for (int i = 0; i < n; i++)
                a[i] = nextInt();
            return a;
        }

        public double[] nextDoubleArray(int n) throws IOException {
            double[] ans = new double[n];
            for (int i = 0; i < n; i++)
                ans[i] = nextDouble();
            return ans;
        }

        public short nextShort() throws IOException {
            return Short.parseShort(next());
        }

    }

}


import java.io.*;
import java.lang.reflect.Array;
import java.math.*;
import java.security.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.regex.*;

public class Solution {

    private static final Scanner sc = new Scanner(System.in);

    public static void main(String[] args) throws IOException {
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        StringTokenizer st = new StringTokenizer(br.readLine());
        int[] arr = new int[n];
        for (int i=0; i<n; ++i){
            arr[i] = (Integer.parseInt(st.nextToken())%2);
        }
        int[] zz = new int[n];
        for (int i=0; i<n; ++i)
            zz[i] = arr[i]^1;
        int ans = solve(arr, n);

        ans |= solve(zz,n);
        System.out.println(ans==0?"NO":"YES");
        sc.close();
        br.close();
        bw.close();
    }

    public static int solve(int[] arr, int n){
        for (int i=1; i<n; ++i){
            if (arr[i] == 1 && arr[i-1]==1){
                arr[i] = 0;
                arr[i-1] = 0;
            }
        }
        int cur0 = 0;
        int cc1 = 0;
        for (int i=0; i<n; ++i){
            if (arr[i] == 0)
                cur0++;
            else {
                cc1++;
                if (cur0%2==1){
                    return 0;
                } else {
                    cur0 = 0;
                }
            }
        }
        if (cc1>0 && cur0%2==1)
            return 0;
        else
            return 1;
    }

}

Vova's family is building the Great Vova Wall (named by Vova himself). Vova's parents, grandparents, grand-grandparents contributed to it. Now it's totally up to Vova to put the finishing touches.The current state of the wall can be respresented by a sequence $$$a$$$ of $$$n$$$ integers, with $$$a_i$$$ being the height of the $$$i$$$-th part of the wall.Vova can only use $$$2 \times 1$$$ bricks to put in the wall (he has infinite supply of them, however).Vova can put bricks horizontally on the neighboring parts of the wall of equal height. It means that if for some $$$i$$$ the current height of part $$$i$$$ is the same as for part $$$i + 1$$$, then Vova can put a brick there and thus increase both heights by 1. Obviously, Vova can't put bricks in such a way that its parts turn out to be off the borders (to the left of part $$$1$$$ of the wall or to the right of part $$$n$$$ of it).The next paragraph is specific to the version 1 of the problem.Vova can also put bricks vertically. That means increasing height of any part of the wall by 2.Vova is a perfectionist, so he considers the wall completed when:  all parts of the wall has the same height;  the wall has no empty spaces inside it. Can Vova complete the wall using any amount of bricks (possibly zero)?

The first line contains a single integer $$$n$$$ ($$$1 \le n \le 2 \cdot 10^5$$$) — the number of parts in the wall. The second line contains $$$n$$$ integers $$$a_1, a_2, \dots, a_n$$$ ($$$1 \le a_i \le 10^9$$$) — the initial heights of the parts of the wall.

Print "YES" if Vova can complete the wall using any amount of bricks (possibly zero). Print "NO" otherwise.

NoteIn the first example Vova can put a brick on parts 2 and 3 to make the wall $$$[2, 2, 2, 2, 5]$$$ and then put 3 bricks on parts 1 and 2 and 3 bricks on parts 3 and 4 to make it $$$[5, 5, 5, 5, 5]$$$.In the second example Vova can put a brick vertically on part 3 to make the wall $$$[4, 5, 5]$$$, then horizontally on parts 2 and 3 to make it $$$[4, 6, 6]$$$ and then vertically on part 1 to make it $$$[6, 6, 6]$$$.In the third example the wall is already complete.

import java.io.*;
import java.lang.reflect.Array;
import java.math.*;
import java.security.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.regex.*;

public class Solution {

    private static final Scanner sc = new Scanner(System.in);

    public static void main(String[] args) throws IOException {
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        StringTokenizer st = new StringTokenizer(br.readLine());
        int[] arr = new int[n];
        for (int i=0; i<n; ++i){
            arr[i] = Integer.parseInt(st.nextToken())%2;
        }
        int[] zz = new int[n];
        for (int i=0; i<n; ++i)
            zz[i] = arr[i]^1;
        int ans = solve(arr,n);
        ans |= solve(zz,n);
        System.out.println(ans==1?"YES":"NO");
        sc.close();
        br.close();
        bw.close();
    }

    public static int solve(int[] arr, int n){
        Stack<Integer> stack = new Stack<>();
        for (int i=0; i<n; ++i){
            if (stack.isEmpty())
                stack.add(arr[i]);
            else {
                if (arr[i] > stack.peek()){
                    stack.add(arr[i]);
                } else if (arr[i] == stack.peek())
                    stack.pop();
                else stack.add(arr[i]);
            }
        }
        if (stack.size() > 1){
            return 0;
        }
        return 1;
    }

}


import java.io.*;
import java.math.*;
import java.util.*;

import static java.util.Arrays.fill;
import static java.lang.Math.*;
import static java.util.Arrays.sort;
import static java.util.Collections.sort;

public class A213
{

	public static int mod = 1000000007;
	public static long INF = (1L << 60);
	static FastScanner2 in = new FastScanner2();
	static OutputWriter out = new OutputWriter(System.out);
	static int n;
	static ArrayList<Integer>[] parent;
	static ArrayList<Integer>[] child;
	static int[] color;
	static int[] done;
	public static int solve(int pos)
	{
		int ret=n;
		int count=0;
		int it=0;
		while(true)
		{
			boolean one=false;
			for(int i=1;i<=n;i++)
			{
				it++;
				if(done[i]==parent[i].size() && pos==color[i])
				{
					done[i]=-1000;
					for(int j : child[i])
						{
						done[j]++;
						}
					one=true;
					count++;
				}
			}
			if(one)
				continue;  //to check interdependence
			if(count==n)
				break;
			pos++;
			ret++;
			if(pos>3)
				pos-=3;
		}
		if(n!=1 && it>3*n*n)
			System.out.println("smk");
		return ret;
	}
	public static void main(String[] args)
	{

		n=in.nextInt();
		color=new int[n+1];
		parent=new ArrayList[n+1];
		child=new ArrayList[n+1];
		done=new int[n+1];
		for(int i=1;i<=n;i++)
		{
			color[i]=in.nextInt();
			parent[i]=new ArrayList<>();
			child[i]=new ArrayList<>();
		}
		for(int i=1;i<=n;i++)
		{
			int x=in.nextInt();
			while(x-->0)
			{
				int t=in.nextInt();
				parent[i].add(t);
				child[t].add(i);
			}
		}
		int answer=mod;
		for(int i=1;i<=3;i++)
		{
			Arrays.fill(done, 0);
			answer=min(answer, solve(i));
		}
		out.println(answer);
		out.close();

	}

	public static long pow(long x, long n)
	{
		long res = 1;
		for (long p = x; n > 0; n >>= 1, p = (p * p))
		{
			if ((n & 1) != 0)
			{
				res = (res * p);
			}
		}
		return res;
	}

	public static long pow(long x, long n, long mod)
	{
		long res = 1;
		for (long p = x; n > 0; n >>= 1, p = (p * p) % mod)
		{
			if ((n & 1) != 0)
			{
				res = (res * p % mod);
			}
		}
		return res;
	}

	public static long gcd(long n1, long n2)
	{
		long r;
		while (n2 != 0)
		{
			r = n1 % n2;
			n1 = n2;
			n2 = r;
		}
		return n1;
	}

	public static long lcm(long n1, long n2)
	{
		long answer = (n1 * n2) / (gcd(n1, n2));
		return answer;
	}

	static class FastScanner2
	{
		private byte[] buf = new byte[1024];
		private int curChar;
		private int snumChars;

		public int read()
		{
			if (snumChars == -1)
				throw new InputMismatchException();
			if (curChar >= snumChars)
			{
				curChar = 0;
				try
				{
					snumChars = System.in.read(buf);
				} catch (IOException e)
				{
					throw new InputMismatchException();
				}
				if (snumChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		public String nextLine()
		{
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do
			{
				res.appendCodePoint(c);
				c = read();
			}
			while (!isEndOfLine(c));
			return res.toString();
		}

		public String nextString()
		{
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do
			{
				res.appendCodePoint(c);
				c = read();
			}
			while (!isSpaceChar(c));
			return res.toString();
		}

		public long nextLong()
		{
			int c = read();
			while (isSpaceChar(c))
				c = read();
			int sgn = 1;
			if (c == '-') {
				sgn = -1;
				c = read();
			}
			long res = 0;
			do
			{
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			}
			while (!isSpaceChar(c));
			return res * sgn;
		}

		public int nextInt()
		{
			int c = read();
			while (isSpaceChar(c))
				c = read();
			int sgn = 1;
			if (c == '-') {
				sgn = -1;
				c = read();
			}
			int res = 0;
			do
			{
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = read();
			}
			while (!isSpaceChar(c));
			return res * sgn;
		}

		public int[] nextIntArray(int n)
		{
			int[] arr = new int[n];
			for (int i = 0; i < n; i++)
			{
				arr[i] = nextInt();
			}
			return arr;
		}

		public long[] nextLongArray(int n)
		{
			long[] arr = new long[n];
			for (int i = 0; i < n; i++)
			{
				arr[i] = nextLong();
			}
			return arr;
		}

		private boolean isSpaceChar(int c)
		{
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		private boolean isEndOfLine(int c)
		{
			return c == '\n' || c == '\r' || c == -1;
		}
	}

	static class InputReader
	{
		public BufferedReader reader;
		public StringTokenizer tokenizer;

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

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

		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 long nextLong()
		{
			return Long.parseLong(next());
		}

		public int[] nextIntArray(int n)
		{
			int a[] = new int[n];
			for (int i = 0; i < n; i++)
			{
				a[i] = nextInt();
			}
			return a;
		}

		public long[] nextLongArray(int n)
		{
			long a[] = new long[n];
			for (int i = 0; i < n; i++)
			{
				a[i] = nextLong();
			}
			return a;
		}

		public int nextInt()
		{
			return Integer.parseInt(next());
		}
	}

	static class OutputWriter
	{
		private final PrintWriter writer;

		public OutputWriter(OutputStream outputStream)
		{
			writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
		}

		public OutputWriter(Writer writer)
		{
			this.writer = new PrintWriter(writer);
		}

		public void print(Object... objects)
		{
			for (int i = 0; i < objects.length; i++)
			{
				if (i != 0)
					writer.print(' ');
				writer.print(objects[i]);
			}
		}

		public void println(Object... objects)
		{
			print(objects);
			writer.println();
		}

		public void close()
		{
			writer.close();
		}

		public void flush()
		{
			writer.flush();
		}
	}
private static boolean oj = System.getProperty("ONLINE_JUDGE") != null;

	private static void tr(Object... o)
	{
		if (!oj)
			System.out.println(Arrays.deepToString(o));
	}
}

Furik and Rubik love playing computer games. Furik has recently found a new game that greatly interested Rubik. The game consists of n parts and to complete each part a player may probably need to complete some other ones. We know that the game can be fully completed, that is, its parts do not form cyclic dependencies. Rubik has 3 computers, on which he can play this game. All computers are located in different houses. Besides, it has turned out that each part of the game can be completed only on one of these computers. Let's number the computers with integers from 1 to 3. Rubik can perform the following actions:   Complete some part of the game on some computer. Rubik spends exactly 1 hour on completing any part on any computer.  Move from the 1-st computer to the 2-nd one. Rubik spends exactly 1 hour on that.  Move from the 1-st computer to the 3-rd one. Rubik spends exactly 2 hours on that.  Move from the 2-nd computer to the 1-st one. Rubik spends exactly 2 hours on that.  Move from the 2-nd computer to the 3-rd one. Rubik spends exactly 1 hour on that.  Move from the 3-rd computer to the 1-st one. Rubik spends exactly 1 hour on that.  Move from the 3-rd computer to the 2-nd one. Rubik spends exactly 2 hours on that. Help Rubik to find the minimum number of hours he will need to complete all parts of the game. Initially Rubik can be located at the computer he considers necessary.

The first line contains integer n (1 ≤ n ≤ 200) — the number of game parts. The next line contains n integers, the i-th integer — ci (1 ≤ ci ≤ 3) represents the number of the computer, on which you can complete the game part number i.  Next n lines contain descriptions of game parts. The i-th line first contains integer ki (0 ≤ ki ≤ n - 1), then ki distinct integers ai, j (1 ≤ ai, j ≤ n; ai, j ≠ i) — the numbers of parts to complete before part i. Numbers on all lines are separated by single spaces. You can assume that the parts of the game are numbered from 1 to n in some way. It is guaranteed that there are no cyclic dependencies between the parts of the game.

On a single line print the answer to the problem.

NoteNote to the second sample: before the beginning of the game the best strategy is to stand by the third computer. First we complete part 5. Then we go to the 1-st computer and complete parts 3 and 4. Then we go to the 2-nd computer and complete parts 1 and 2. In total we get 1+1+2+1+2, which equals 7 hours.

import java.util.List;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.ArrayList;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.math.BigInteger;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author AlexFetisov
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskA solver = new TaskA();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskA {

    private int n;
    private int[] completeOn;
    private int[] degIn;
    private boolean[][] g;

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        n = in.nextInt();
        completeOn = Utils.readIntArray(in, n);
        degIn = new int[n];
        g = new boolean[n][n];
        for (int i = 0; i < n; ++i) {
            int am = in.nextInt();
            for (int j = 0; j < am; ++j) {
                int x = in.nextInt()-1;
                g[x][i] = true;
                degIn[i]++;
            }
        }
        int res = Integer.MAX_VALUE;
        for (int i = 1; i <= 3; ++i) {
            res = Math.min(res, process(i));
        }
        out.println(res);
    }

    private int process(int cur) {
        boolean[] visited = new boolean[n];
        int cost = 0;
        int[] curDegIn = degIn.clone();
        while (true) {
            boolean finished = true;
            List<Integer> queue = new ArrayList<Integer>();
            for (int i = 0; i < n; ++i) {
                if (!visited[i]) {
                    finished = false;
                    if (curDegIn[i] == 0 && completeOn[i] == cur) {
                        queue.add(i);
                    }
                }
            }
            if (finished) break;
            if (queue.size() == 0) {
                cur++;
                ++cost;
                if (cur == 4) {
                    cur = 1;
                }
                continue;
            }
            for (int x : queue) {
                ++cost;
                visited[x] = true;
                for (int i = 0; i < n; ++i) {
                    if (g[x][i]) {
                        --curDegIn[i];
                    }
                }
            }
        }
        return cost;
    }
}

class InputReader {
    private BufferedReader reader;
    private StringTokenizer stt;

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

    public String nextLine() {
        try {
            return reader.readLine();
        } catch (IOException e) {
            return null;
        }
    }

    public String nextString() {
        while (stt == null || !stt.hasMoreTokens()) {
            stt = new StringTokenizer(nextLine());
        }
        return stt.nextToken();
    }

    public int nextInt() {
        return Integer.parseInt(nextString());
    }

}

class Utils {
    public static int[] readIntArray(InputReader in, int n) {
        int[] a = new int[n];
        for (int i = 0; i < n; ++i) {
            a[i] = in.nextInt();
        }
        return a;
    }

}


import java.io.InputStreamReader;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.InputStream;

public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		Task solver = new Task();
		solver.solve(1, in, out);
		out.close();
	}
}

class Task {

	public void solve(int testNumber, InputReader in, PrintWriter out) {
		int n = in.nextInt();
		int m = in.nextInt();
		int[] positive = new int[n];
		int[] negative = new int[n];
		int cnt = 0;
		String[] memo = new String[n];
		for (int k = 0; k < n; ++k) {
			String s = in.next();
			memo[k] = s;
			int id = Integer.parseInt(s.substring(1)) - 1;
			if (s.startsWith("+")) {
				positive[id]++;
			} else {
				negative[id]++;
				cnt++;
			}
		}

		boolean[] maybe = new boolean[n];
		int all = 0;
		for (int k = 0; k < n; ++k) {
			int tmp = cnt + positive[k] - negative[k];
			if (tmp == m) {
				maybe[k] = true;
				all++;
			}
		}

		for (int k = 0; k < n; ++k) {
			String s = memo[k];
			int id = Integer.parseInt(s.substring(1)) - 1;
			if (s.startsWith("+")) {
				if (!maybe[id]) {
					out.println("Lie");
				} else {
					out.println(all == 1 ? "True" : "Not defined");
				}
			} else {
				if (!maybe[id]) {
					out.println("True");
				} else {
					out.println(all == 1 ? "Lie" : "Not defined");
				}
			}
		}

	}
}

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());
    }
}

As Sherlock Holmes was investigating a crime, he identified n suspects. He knows for sure that exactly one of them committed the crime. To find out which one did it, the detective lines up the suspects and numbered them from 1 to n. After that, he asked each one: "Which one committed the crime?". Suspect number i answered either "The crime was committed by suspect number ai", or "Suspect number ai didn't commit the crime". Also, the suspect could say so about himself (ai = i).Sherlock Holmes understood for sure that exactly m answers were the truth and all other answers were a lie. Now help him understand this: which suspect lied and which one told the truth?

The first line contains two integers n and m (1 ≤ n ≤ 105, 0 ≤ m ≤ n) — the total number of suspects and the number of suspects who told the truth. Next n lines contain the suspects' answers. The i-th line contains either "+ai" (without the quotes), if the suspect number i says that the crime was committed by suspect number ai, or "-ai" (without the quotes), if the suspect number i says that the suspect number ai didn't commit the crime (ai is an integer, 1 ≤ ai ≤ n). It is guaranteed that at least one suspect exists, such that if he committed the crime, then exactly m people told the truth.

Print n lines. Line number i should contain "Truth" if suspect number i has told the truth for sure. Print "Lie" if the suspect number i lied for sure and print "Not defined" if he could lie and could tell the truth, too, depending on who committed the crime.

NoteThe first sample has the single person and he confesses to the crime, and Sherlock Holmes knows that one person is telling the truth. That means that this person is telling the truth.In the second sample there are three suspects and each one denies his guilt. Sherlock Holmes knows that only two of them are telling the truth. Any one of them can be the criminal, so we don't know for any of them, whether this person is telling the truth or not.In the third sample the second and the fourth suspect defend the first and the third one. But only one is telling the truth, thus, the first or the third one is the criminal. Both of them can be criminals, so the second and the fourth one can either be lying or telling the truth. The first and the third one are lying for sure as they are blaming the second and the fourth one.

// practice with kaiboy
import java.io.*;
import java.util.*;

public class CF157D extends PrintWriter {
	CF157D() { super(System.out); }
	Scanner sc = new Scanner(System.in);
	public static void main(String[] $) {
		CF157D o = new CF157D(); o.main(); o.flush();
	}

	void main() {
		int n = sc.nextInt();
		int m = sc.nextInt();
		int[] aa = new int[n];
		int[] pp = new int[n + 1];
		int[] qq = new int[n + 1];
		int q = 0;
		for (int i = 0; i < n; i++) {
			int a = sc.nextInt();
			aa[i] = a;
			if (a > 0)
				pp[a]++;
			else {
				qq[-a]++;
				q++;
			}
		}
		boolean[] yes = new boolean[n + 1];
		int k = 0;
		for (int a = 1; a <= n; a++)
			if (pp[a] + q - qq[a] == m) {
				yes[a] = true;
				k++;
			}
		for (int i = 0; i < n; i++) {
			int a = aa[i];
			if (a > 0)
				println(yes[a] ? (k == 1 ? "Truth" : "Not defined") : "Lie");
			else
				println(yes[-a] ? (k == 1 ? "Lie" : "Not defined") : "Truth");
		}
	}
}

[{'input': '1 1\r\n+1\r\n', 'output': ['Truth\r\n']}, {'input': '3 2\r\n-1\r\n-2\r\n-3\r\n', 'output': ['Not defined\r\nNot defined\r\nNot defined\r\n']}, {'input': '4 1\r\n+2\r\n-3\r\n+4\r\n-1\r\n', 'output': ['Lie\r\nNot defined\r\nLie\r\nNot defined\r\n']}, {'input': '1 0\r\n-1\r\n', 'output': ['Lie\r\n']}, {'input': '2 2\r\n+1\r\n+1\r\n', 'output': ['Truth\r\nTruth\r\n']}, {'input': '2 1\r\n+2\r\n+1\r\n', 'output': ['Not defined\r\nNot defined\r\n']}, {'input': '2 0\r\n-2\r\n-2\r\n', 'output': ['Lie\r\nLie\r\n']}, {'input': '3 1\r\n+2\r\n+3\r\n+3\r\n', 'output': ['Truth\r\nLie\r\nLie\r\n']}, {'input': '6 3\r\n+5\r\n+5\r\n+5\r\n+1\r\n+1\r\n+1\r\n', 'output': ['Not defined\r\nNot defined\r\nNot defined\r\nNot defined\r\nNot defined\r\nNot defined\r\n']}, {'input': '4 3\r\n-4\r\n-3\r\n-1\r\n-3\r\n', 'output': ['Not defined\r\nTruth\r\nNot defined\r\nTruth\r\n']}, {'input': '10 4\r\n-8\r\n+1\r\n-6\r\n-10\r\n+5\r\n-6\r\n-8\r\n-8\r\n-4\r\n-8\r\n', 'output': ['Lie\r\nLie\r\nTruth\r\nTruth\r\nLie\r\nTruth\r\nLie\r\nLie\r\nTruth\r\nLie\r\n']}, {'input': '10 5\r\n-4\r\n+4\r\n+4\r\n-9\r\n-9\r\n-4\r\n-4\r\n+2\r\n-9\r\n-4\r\n', 'output': ['Lie\r\nTruth\r\nTruth\r\nTruth\r\nTruth\r\nLie\r\nLie\r\nLie\r\nTruth\r\nLie\r\n']}, {'input': '7 2\r\n+5\r\n+5\r\n+5\r\n-2\r\n+1\r\n-5\r\n-6\r\n', 'output': ['Lie\r\nLie\r\nLie\r\nNot defined\r\nLie\r\nTruth\r\nNot defined\r\n']}, {'input': '7 4\r\n+7\r\n-3\r\n-3\r\n-4\r\n+3\r\n+3\r\n+3\r\n', 'output': ['Not defined\r\nNot defined\r\nNot defined\r\nTruth\r\nNot defined\r\nNot defined\r\nNot defined\r\n']}, {'input': '6 3\r\n-6\r\n-1\r\n+5\r\n+1\r\n+6\r\n+1\r\n', 'output': ['Truth\r\nNot defined\r\nNot defined\r\nNot defined\r\nLie\r\nNot defined\r\n']}, {'input': '5 3\r\n-2\r\n+2\r\n+2\r\n-3\r\n+5\r\n', 'output': ['Not defined\r\nNot defined\r\nNot defined\r\nTruth\r\nNot defined\r\n']}, {'input': '3 0\r\n-2\r\n-2\r\n-2\r\n', 'output': ['Lie\r\nLie\r\nLie\r\n']}, {'input': '5 3\r\n-1\r\n-1\r\n-4\r\n+1\r\n-4\r\n', 'output': ['Lie\r\nLie\r\nTruth\r\nTruth\r\nTruth\r\n']}, {'input': '9 6\r\n+2\r\n+7\r\n+7\r\n-1\r\n-4\r\n+7\r\n-7\r\n+7\r\n+5\r\n', 'output': ['Lie\r\nTruth\r\nTruth\r\nTruth\r\nTruth\r\nTruth\r\nLie\r\nTruth\r\nLie\r\n']}, {'input': '43 18\r\n-14\r\n-28\r\n+16\r\n+10\r\n+25\r\n-30\r\n+25\r\n+30\r\n+25\r\n+25\r\n+25\r\n+25\r\n-25\r\n+22\r\n+3\r\n-17\r\n+16\r\n-25\r\n+10\r\n+14\r\n+41\r\n+25\r\n-25\r\n+33\r\n+24\r\n-23\r\n-25\r\n+25\r\n-22\r\n+29\r\n+28\r\n-25\r\n-25\r\n-29\r\n+11\r\n+26\r\n-25\r\n+25\r\n+10\r\n+1\r\n-20\r\n-17\r\n+23\r\n', 'output': ['Truth\r\nTruth\r\nNot defined\r\nLie\r\nNot defined\r\nTruth\r\nNot defined\r\nLie\r\nNot defined\r\nNot defined\r\nNot defined\r\nNot defined\r\nNot defined\r\nLie\r\nLie\r\nTruth\r\nNot defined\r\nNot defined\r\nLie\r\nLie\r\nLie\r\nNot defined\r\nNot defined\r\nLie\r\nLie\r\nTruth\r\nNot defined\r\nNot defined\r\nTruth\r\nLie\r\nLie\r\nNot defined\r\nNot defined\r\nTruth\r\nLie\r\nLie\r\nNot defined\r\nNot defined\r\nLie\r\nLie\r\nTruth\r\nTruth\r\nLie\r\n']}, {'input': '28 12\r\n+10\r\n-7\r\n+17\r\n-20\r\n+7\r\n-7\r\n+13\r\n-21\r\n-7\r\n-7\r\n-18\r\n+7\r\n+7\r\n+3\r\n+6\r\n+14\r\n+7\r\n-24\r\n-21\r\n-7\r\n-7\r\n+4\r\n+7\r\n-7\r\n+21\r\n-7\r\n-26\r\n+7\r\n', 'output': ['Lie\r\nLie\r\nLie\r\nTruth\r\nTruth\r\nLie\r\nLie\r\nTruth\r\nLie\r\nLie\r\nTruth\r\nTruth\r\nTruth\r\nLie\r\nLie\r\nLie\r\nTruth\r\nTruth\r\nTruth\r\nLie\r\nLie\r\nLie\r\nTruth\r\nLie\r\nLie\r\nLie\r\nTruth\r\nTruth\r\n']}, {'input': '17 9\r\n-6\r\n+16\r\n+5\r\n+16\r\n-17\r\n+17\r\n-11\r\n+5\r\n+14\r\n+5\r\n-8\r\n-5\r\n+6\r\n-2\r\n-11\r\n+4\r\n+17\r\n', 'output': ['Truth\r\nNot defined\r\nNot defined\r\nNot defined\r\nTruth\r\nLie\r\nTruth\r\nNot defined\r\nLie\r\nNot defined\r\nTruth\r\nNot defined\r\nLie\r\nTruth\r\nTruth\r\nLie\r\nLie\r\n']}, {'input': '14 3\r\n+14\r\n+12\r\n-9\r\n+9\r\n-9\r\n-9\r\n+8\r\n+9\r\n+2\r\n+1\r\n-13\r\n-9\r\n+13\r\n+3\r\n', 'output': ['Lie\r\nLie\r\nLie\r\nTruth\r\nLie\r\nLie\r\nLie\r\nTruth\r\nLie\r\nLie\r\nTruth\r\nLie\r\nLie\r\nLie\r\n']}, {'input': '10 4\r\n-9\r\n-8\r\n-5\r\n-9\r\n-7\r\n-9\r\n-9\r\n-9\r\n-4\r\n-9\r\n', 'output': ['Lie\r\nTruth\r\nTruth\r\nLie\r\nTruth\r\nLie\r\nLie\r\nLie\r\nTruth\r\nLie\r\n']}, {'input': '10 5\r\n-10\r\n-10\r\n-10\r\n-5\r\n-1\r\n+10\r\n-3\r\n-10\r\n-9\r\n-10\r\n', 'output': ['Lie\r\nLie\r\nLie\r\nTruth\r\nTruth\r\nTruth\r\nTruth\r\nLie\r\nTruth\r\nLie\r\n']}, {'input': '10 4\r\n-3\r\n-3\r\n-3\r\n-3\r\n-3\r\n-2\r\n-2\r\n-6\r\n-7\r\n-3\r\n', 'output': ['Lie\r\nLie\r\nLie\r\nLie\r\nLie\r\nTruth\r\nTruth\r\nTruth\r\nTruth\r\nLie\r\n']}, {'input': '10 6\r\n-9\r\n-7\r\n-5\r\n-5\r\n-4\r\n-2\r\n-8\r\n-5\r\n-5\r\n-9\r\n', 'output': ['Truth\r\nTruth\r\nLie\r\nLie\r\nTruth\r\nTruth\r\nTruth\r\nLie\r\nLie\r\nTruth\r\n']}, {'input': '10 4\r\n-8\r\n-2\r\n-8\r\n+1\r\n-4\r\n-8\r\n-2\r\n-8\r\n-8\r\n-1\r\n', 'output': ['Lie\r\nTruth\r\nLie\r\nLie\r\nTruth\r\nLie\r\nTruth\r\nLie\r\nLie\r\nTruth\r\n']}, {'input': '10 2\r\n-8\r\n+10\r\n+1\r\n+8\r\n+4\r\n+8\r\n+6\r\n-8\r\n+10\r\n+1\r\n', 'output': ['Not defined\r\nLie\r\nLie\r\nNot defined\r\nLie\r\nNot defined\r\nLie\r\nNot defined\r\nLie\r\nLie\r\n']}, {'input': '10 3\r\n+9\r\n+3\r\n+8\r\n+3\r\n+6\r\n-3\r\n+6\r\n+8\r\n+3\r\n+7\r\n', 'output': ['Lie\r\nNot defined\r\nNot defined\r\nNot defined\r\nNot defined\r\nNot defined\r\nNot defined\r\nNot defined\r\nNot defined\r\nLie\r\n']}, {'input': '10 8\r\n-2\r\n+9\r\n+9\r\n-4\r\n+9\r\n+9\r\n+4\r\n-9\r\n-3\r\n+9\r\n', 'output': ['Truth\r\nTruth\r\nTruth\r\nTruth\r\nTruth\r\nTruth\r\nLie\r\nLie\r\nTruth\r\nTruth\r\n']}, {'input': '10 7\r\n-4\r\n+6\r\n+4\r\n+9\r\n+6\r\n+6\r\n+6\r\n+6\r\n+6\r\n+2\r\n', 'output': ['Truth\r\nTruth\r\nLie\r\nLie\r\nTruth\r\nTruth\r\nTruth\r\nTruth\r\nTruth\r\nLie\r\n']}, {'input': '10 4\r\n+3\r\n+5\r\n+6\r\n+10\r\n+5\r\n+5\r\n+6\r\n+8\r\n+5\r\n+6\r\n', 'output': ['Lie\r\nTruth\r\nLie\r\nLie\r\nTruth\r\nTruth\r\nLie\r\nLie\r\nTruth\r\nLie\r\n']}, {'input': '10 7\r\n-6\r\n-10\r\n-3\r\n-1\r\n-3\r\n-7\r\n-2\r\n-7\r\n-7\r\n-3\r\n', 'output': ['Truth\r\nTruth\r\nNot defined\r\nTruth\r\nNot defined\r\nNot defined\r\nTruth\r\nNot defined\r\nNot defined\r\nNot defined\r\n']}, {'input': '10 5\r\n-4\r\n-4\r\n-1\r\n-5\r\n-7\r\n-4\r\n-4\r\n-4\r\n-1\r\n-7\r\n', 'output': ['Lie\r\nLie\r\nTruth\r\nTruth\r\nTruth\r\nLie\r\nLie\r\nLie\r\nTruth\r\nTruth\r\n']}, {'input': '10 5\r\n-9\r\n-7\r\n-6\r\n-3\r\n-10\r\n-10\r\n-10\r\n-10\r\n-10\r\n-2\r\n', 'output': ['Truth\r\nTruth\r\nTruth\r\nTruth\r\nLie\r\nLie\r\nLie\r\nLie\r\nLie\r\nTruth\r\n']}, {'input': '10 3\r\n-10\r\n-10\r\n-10\r\n-3\r\n-10\r\n-10\r\n-10\r\n-8\r\n-4\r\n-10\r\n', 'output': ['Lie\r\nLie\r\nLie\r\nTruth\r\nLie\r\nLie\r\nLie\r\nTruth\r\nTruth\r\nLie\r\n']}, {'input': '10 5\r\n-8\r\n-8\r\n-4\r\n-9\r\n-10\r\n-2\r\n-9\r\n-8\r\n-8\r\n-8\r\n', 'output': ['Lie\r\nLie\r\nTruth\r\nTruth\r\nTruth\r\nTruth\r\nTruth\r\nLie\r\nLie\r\nLie\r\n']}, {'input': '10 5\r\n+7\r\n+8\r\n+9\r\n+1\r\n+7\r\n+7\r\n+7\r\n+6\r\n+6\r\n+7\r\n', 'output': ['Truth\r\nLie\r\nLie\r\nLie\r\nTruth\r\nTruth\r\nTruth\r\nLie\r\nLie\r\nTruth\r\n']}, {'input': '10 5\r\n+2\r\n+2\r\n+2\r\n+2\r\n+9\r\n+10\r\n+8\r\n+7\r\n+4\r\n+2\r\n', 'output': ['Truth\r\nTruth\r\nTruth\r\nTruth\r\nLie\r\nLie\r\nLie\r\nLie\r\nLie\r\nTruth\r\n']}, {'input': '10 9\r\n+7\r\n+7\r\n+7\r\n+7\r\n+7\r\n+7\r\n+5\r\n+7\r\n+7\r\n+7\r\n', 'output': ['Truth\r\nTruth\r\nTruth\r\nTruth\r\nTruth\r\nTruth\r\nLie\r\nTruth\r\nTruth\r\nTruth\r\n']}, {'input': '10 3\r\n+10\r\n+2\r\n+10\r\n+9\r\n+1\r\n+9\r\n+4\r\n+9\r\n+3\r\n+2\r\n', 'output': ['Lie\r\nLie\r\nLie\r\nTruth\r\nLie\r\nTruth\r\nLie\r\nTruth\r\nLie\r\nLie\r\n']}, {'input': '10 6\r\n+10\r\n+10\r\n+10\r\n+3\r\n+10\r\n+10\r\n+6\r\n+6\r\n+10\r\n+8\r\n', 'output': ['Truth\r\nTruth\r\nTruth\r\nLie\r\nTruth\r\nTruth\r\nLie\r\nLie\r\nTruth\r\nLie\r\n']}, {'input': '3 2\r\n-1\r\n+2\r\n+3\r\n', 'output': ['Truth\r\nNot defined\r\nNot defined\r\n']}]


import java.io.*;
import java.lang.Math;
import java.util.Scanner;

public class main
{
	public static Scanner in;
	public static PrintStream out;

	public static void test()
	{
		int ti = in.nextInt();
		int td = in.nextInt();
		int tr = in.nextInt();
		int te = in.nextInt();

		in.nextLine();

		String A = in.nextLine();

		if (A.length()==0)
		{
			A = in.nextLine();
		}

		String B = in.nextLine();

		int N = A.length();
		int M = B.length();

		int i,j;

		int t[][] = new int[N+1][];
		for (i=0; i<=N; i++)
		{
			t[i] = new int[M+1];
		}

		t[0][0] = 0;
		for (i=1; i<=N; i++)
		{
			t[i][0] = td * i;
		}
		for (j=1; j<=M; j++)
		{
			t[0][j] = ti * j;
		}

		int m;
		for (i=1; i<=N; i++)
		{
			for (j=1;j<=M;j++)
			{
				m = tr + t[i-1][j-1];

				if (A.charAt(i-1) == B.charAt(j-1))
				{
					m = Math.min(m, t[i-1][j-1]);
				}

				m = Math.min(m, td + t[i-1][j]);
				m = Math.min(m, ti + t[i][j-1]);

				if ((i>1)&&(j>1)&&(A.charAt(i-1) == B.charAt(j-2))&&(A.charAt(i-2) == B.charAt(j-1)))
				{
					m = Math.min(m, te + t[i-2][j-2]);
				}

				t[i][j] = m;
			}
		}

		out.println(t[N][M]);
	}

	public static void main(String args[])
	{
		try
		{
			//in = new Scanner(new File("in.txt"));
			//out = new PrintStream(new File("out.txt"));
			in = new Scanner(System.in);
			out = System.out;
		}
		catch (Exception e)
		{
			return;
		}

		test();
	}
}

You are given a sequence of balls A by your teacher, each labeled with a lowercase Latin letter 'a'-'z'. You don't like the given sequence. You want to change it into a new sequence, B that suits you better. So, you allow yourself four operations:  You can insert any ball with any label into the sequence at any position.  You can delete (remove) any ball from any position.  You can replace any ball with any other ball.  You can exchange (swap) two adjacent balls. Your teacher now places time constraints on each operation, meaning that an operation can only be performed in certain time. So, the first operation takes time ti, the second one takes td, the third one takes tr and the fourth one takes te. Also, it is given that 2·te ≥ ti + td.Find the minimal time to convert the sequence A to the sequence B.

The first line contains four space-separated integers ti, td, tr, te (0 < ti, td, tr, te ≤ 100). The following two lines contain sequences A and B on separate lines. The length of each line is between 1 and 4000 characters inclusive.

Print a single integer representing minimum time to convert A into B.

NoteIn the second sample, you could delete the ball labeled 'a' from the first position and then insert another 'a' at the new second position with total time 6. However exchanging the balls give total time 3.

import java.io.*;
import java.util.*;

public class Main {

    public static int[] toIntArray(String s)
    {
        int[] res = new int[s.length()];
        for (int i = 0; i < res.length; i++) {
            res[i] = s.charAt(i) - 'a';
        }
        return res;
    }

    public static void main(String[] args) throws IOException {
        Scanner in = new Scanner(System.in);
        int ci = in.nextInt();
        int cd = in.nextInt();
        int cr = in.nextInt();
        int cx = in.nextInt();

        int[] a = toIntArray(in.next());
        int[] b = toIntArray(in.next());
        int n = a.length;
        int m = b.length;

        int[][] res = new int[n + 1][m + 1];
        int[][] nA = new int[26][n + 1];
        int[][] nB = new int[26][m + 1];
        for (int i = 0; i < 26; i++) {
            for (int j = n - 1; j >= 0; j--) {
                nA[i][j] = a[j] == i ? j : nA[i][j + 1];
                res[j][m] = (n - j) * cd;
            }
            for (int j = m - 1; j >= 0; j--) {
                nB[i][j] = b[j] == i ? j : nB[i][j + 1];
                res[n][j] = (m - j) * ci;
            }
        }

        for (int i = n - 1; i >= 0; i--) {
            for (int j = m - 1; j >= 0; j--) {
                res[i][j] = res[i + 1][j + 1];
                if (a[i] != b[j]) {
                    int x = Math.min(res[i + 1][j] + cd, Math.min(res[i][j + 1] + ci, res[i + 1][j + 1] + cr));
                    int l = nA[b[j]][i + 1];
                    int r = nB[a[i]][j + 1];
                    if (l > 0 && r > 0) {
                        x = Math.min(x, res[l + 1][r + 1] + (l - i - 1) * cd + (r - j - 1) * ci + cx);
                    }
                    res[i][j] = x;
                }
            }
        }
        System.out.println(res[0][0]);
    }
}

[{'input': '1 1 1 1\r\nyoushouldnot\r\nthoushaltnot\r\n', 'output': ['5\r\n']}, {'input': '2 4 10 3\r\nab\r\nba\r\n', 'output': ['3\r\n']}, {'input': '1 10 20 30\r\na\r\nza\r\n', 'output': ['1\r\n']}, {'input': '2 6 10 4\r\nmanthan\r\nmathmania\r\n', 'output': ['12\r\n']}, {'input': '5 1 5 3\r\nabhishek\r\naurbhishek\r\n', 'output': ['10\r\n']}, {'input': '1 1 100 1\r\nabcd\r\nwxyz\r\n', 'output': ['8\r\n']}, {'input': '4 6 5 5\r\ntest\r\ntsar\r\n', 'output': ['15\r\n']}, {'input': '2 4 10 3\r\nmanthan\r\nnahtnam\r\n', 'output': ['15\r\n']}, {'input': '2 4 100 3\r\nabcd\r\nbade\r\n', 'output': ['9\r\n']}, {'input': '5 5 1 5\r\nab\r\nba\r\n', 'output': ['2\r\n']}, {'input': '3 5 100 4\r\ntets\r\ntesat\r\n', 'output': ['7\r\n']}, {'input': '9 1 10 5\r\nabcd\r\ndbca\r\n', 'output': ['20\r\n']}, {'input': '2 2 10 2\r\nabcd\r\nadcb\r\n', 'output': ['6\r\n']}, {'input': '8 4 3 10\r\neekoowppum\r\njgmtlmeuigztfctikegvakfbgbafytbputmeppkuuyjkhagdsftfoueitnhjllolevgpmbtlworxojyzpfdaasckcqqdwdwwrklb\r\n', 'output': ['729\r\n']}, {'input': '5 5 1 82\r\nzmtuomrwesrhvudogmalwhtktfcbglnpbdntqssjcrdwlerfccmkmmhsfgaocchxdxxmeiaunhellstnhnjjmbynmqlzuupbnkrw\r\nglpfybikah\r\n', 'output': ['453\r\n']}, {'input': '20 21 22 84\r\notirbgzzphwwxqtgqyxympiumuyoupngwabrprmyhjpkgpjmez\r\nozvimdjwsyuacgbekgcw\r\n', 'output': ['872\r\n']}, {'input': '4 5 6 62\r\nqibkeavwalpn\r\nmaasevryyxzzqpdcgydb\r\n', 'output': ['89\r\n']}, {'input': '9 8 7 67\r\nejohycekbciwahqybwiy\r\ncpxgvbiwnuytmbwjvrzalydjjgdcmczejwesqrrh\r\n', 'output': ['299\r\n']}, {'input': '44 55 22 80\r\nabcdefghijklmnopqrstuvwxyz\r\nabcdefghijklmnopqrstuvwxyz\r\n', 'output': ['0\r\n']}, {'input': '63 9 44 72\r\nabdabdabdabdabdabdabdabdabdabdabdabdabdabdabdabdabdabdabdabdabdabdabdabd\r\nabdabdabdabdabdabdabdabdabdabdabtdabdabdabdabdabdabdabdabdabdabdabdabdabd\r\n', 'output': ['63\r\n']}, {'input': '1 3 4 2\r\nabc\r\ncxa\r\n', 'output': ['6\r\n']}, {'input': '1 1 1 1\r\nacccb\r\nba\r\n', 'output': ['4\r\n']}, {'input': '1 1 1 1\r\nab\r\nbca\r\n', 'output': ['2\r\n']}, {'input': '1 1 1 1\r\nba\r\nacb\r\n', 'output': ['2\r\n']}, {'input': '1 1 100 1\r\nafffb\r\nbggga\r\n', 'output': ['7\r\n']}, {'input': '1 1 1 1\r\nab\r\nbccccccccccccccccccca\r\n', 'output': ['20\r\n']}, {'input': '100 1 100 60\r\nacb\r\nba\r\n', 'output': ['61\r\n']}]


import java.io.*;
import java.util.*;

public class B implements Runnable {

    private static final boolean ONLINE_JUDGE = System.getProperty("ONLINE_JUDGE") != null;

    private BufferedReader in;
    private PrintWriter out;
    private StringTokenizer tok = new StringTokenizer("");

    private void init() throws FileNotFoundException {
        Locale.setDefault(Locale.US);
        String fileName = "";
        if (ONLINE_JUDGE && fileName.isEmpty()) {
            in = new BufferedReader(new InputStreamReader(System.in));
            out = new PrintWriter(System.out);
        } else {
            if (fileName.isEmpty()) {
                in = new BufferedReader(new FileReader("input.txt"));
                out = new PrintWriter("output.txt");
            } else {
                in = new BufferedReader(new FileReader(fileName + ".in"));
                out = new PrintWriter(fileName + ".out");
            }
        }
    }

    String readString() {
        while (!tok.hasMoreTokens()) {
            try {
                tok = new StringTokenizer(in.readLine());
            } catch (Exception e) {
                return null;
            }
        }
        return tok.nextToken();
    }

    int readInt() {
        return Integer.parseInt(readString());
    }

    long readLong() {
        return Long.parseLong(readString());
    }

    double readDouble() {
        return Double.parseDouble(readString());
    }

    int[] readIntArray(int size) {
        int[] a = new int[size];
        for (int i = 0; i < size; i++) {
            a[i] = readInt();
        }
        return a;
    }

    public static void main(String[] args) {
        //new Thread(null, new _Solution(), "", 128 * (1L << 20)).start();
        new B().run();
    }

    long timeBegin, timeEnd;

    void time() {
        timeEnd = System.currentTimeMillis();
        System.err.println("Time = " + (timeEnd - timeBegin));
    }

    @Override
    public void run() {
        try {
            timeBegin = System.currentTimeMillis();
            init();
            solve();
            out.close();
            time();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(-1);
        }
    }

    int gcd(int a, int b) {
        return a == 0 ? b : gcd(b % a, a);
    }

    long answer = Long.MAX_VALUE;

    private void solve() {
        int n = readInt();

        int A = readInt();
        int B = readInt();
        int[] a = readIntArray(n);

        for (int kFirst = -1; kFirst <= 1; kFirst++) {
            int currentFirst = a[0] + kFirst;
            for (int divisor = 2; divisor * divisor <= currentFirst; divisor++) {
                if (currentFirst % divisor == 0) {
                    answer = Math.min(answer, solveForPrefix(n, a, divisor, A, B));
                }
                while (currentFirst % divisor == 0) {
                    currentFirst /= divisor;
                }
            }
            if (currentFirst > 1) {
                answer = Math.min(answer, solveForPrefix(n, a, currentFirst, A, B));
            }
        }

        int[] b = new int[n];
        for (int i = 0; i < n; i++) {
            b[i] = a[n - i - 1];
        }

        for (int kFirst = -1; kFirst <= 1; kFirst++) {
            int currentFirst = b[0] + kFirst;
            for (int divisor = 2; divisor * divisor <= currentFirst; divisor++) {
                if (currentFirst % divisor == 0) {
                    answer = Math.min(answer, solveForPrefix(n, b, divisor, A, B));
                }
                while (currentFirst % divisor == 0) {
                    currentFirst /= divisor;
                }
            }
            if (currentFirst > 1) {
                answer = Math.min(answer, solveForPrefix(n, b, currentFirst, A, B));
            }
        }
        out.println(answer);
    }

    final int PREFIX = 0;
    final int REMOVED = 1;
    final int SUFFIX = 2;

    long solveForPrefix(int n, int[] a, int gcd, int A, int B) {
        long[][] dp = new long[3][n];
        for (int i = 0; i < 3; i++) {
            Arrays.fill(dp[i], Long.MAX_VALUE);
        }
        dp[PREFIX][0] = a[0] % gcd == 0 ? 0 : B;
        for (int i = 1; i < n; i++) {
            if (dp[PREFIX][i - 1] < Long.MAX_VALUE) {
                if (a[i] % gcd != 0 && (a[i] - 1) % gcd != 0 && (a[i] + 1) % gcd != 0) {
                    dp[PREFIX][i] = Long.MAX_VALUE;
                } else {
                    dp[PREFIX][i] = Math.min(dp[PREFIX][i], dp[PREFIX][i - 1] + (a[i] % gcd == 0 ? 0 : B));
                }
            }

            if (dp[REMOVED][i - 1] < Long.MAX_VALUE) {
                dp[REMOVED][i] = Math.min(dp[REMOVED][i], dp[REMOVED][i - 1] + A);
            }
            if (dp[PREFIX][i - 1] < Long.MAX_VALUE) {
                dp[REMOVED][i] = Math.min(dp[REMOVED][i], dp[PREFIX][i - 1] + A);
            }

            if (dp[REMOVED][i - 1] < Long.MAX_VALUE) {
                if (a[i] % gcd != 0 && (a[i] - 1) % gcd != 0 && (a[i] + 1) % gcd != 0) {
                    dp[SUFFIX][i] = Long.MAX_VALUE;
                } else {
                    dp[SUFFIX][i] = Math.min(dp[SUFFIX][i], dp[REMOVED][i - 1] + (a[i] % gcd == 0 ? 0 : B));
                }
            }
            if (dp[PREFIX][i - 1] < Long.MAX_VALUE) {
                if (a[i] % gcd != 0 && (a[i] - 1) % gcd != 0 && (a[i] + 1) % gcd != 0) {
                    dp[SUFFIX][i] = Long.MAX_VALUE;
                } else {
                    dp[SUFFIX][i] = Math.min(dp[SUFFIX][i], dp[PREFIX][i - 1] + (a[i] % gcd == 0 ? 0 : B));
                }
            }
        }
        return Math.min(dp[PREFIX][n - 1], Math.min(dp[REMOVED][n - 1], dp[SUFFIX][n - 1]));
    }
}

You are given array ai of length n. You may consecutively apply two operations to this array:  remove some subsegment (continuous subsequence) of length m < n and pay for it m·a coins;  change some elements of the array by at most 1, and pay b coins for each change. Please note that each of operations may be applied at most once (and may be not applied at all) so you can remove only one segment and each number may be changed (increased or decreased) by at most 1. Also note, that you are not allowed to delete the whole array.Your goal is to calculate the minimum number of coins that you need to spend in order to make the greatest common divisor of the elements of the resulting array be greater than 1.

The first line of the input contains integers n, a and b (1 ≤ n ≤ 1 000 000, 0 ≤ a, b ≤ 109) — the length of the array, the cost of removing a single element in the first operation and the cost of changing an element, respectively. The second line contains n integers ai (2 ≤ ai ≤ 109) — elements of the array.

Print a single number — the minimum cost of changes needed to obtain an array, such that the greatest common divisor of all its elements is greater than 1.

NoteIn the first sample the optimal way is to remove number 3 and pay 1 coin for it.In the second sample you need to remove a segment [17, 13] and then decrease number 6. The cost of these changes is equal to 2·3 + 2 = 8 coins.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class D {

    public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    public static StringTokenizer tok;

    public static int nextInt() throws IOException {
        return Integer.parseInt(nextToken());
    }

    public static long nextLong() throws IOException {
        return Long.parseLong(nextToken());
    }

    public static double nextDouble() throws IOException {
        return Double.parseDouble(nextToken());
    }

    public static String nextToken() throws IOException {
        if (tok == null || !tok.hasMoreTokens()) {
            tok = new StringTokenizer(in.readLine());
        }
        return tok.nextToken();
    }

//    public static class Pair {
//        public long change, norm;
//        public int index;
//        public Pair(long change, long norm, int index) {
//            this.change = change;
//            this.norm = norm;
//            this.index = index;
//        }
//    }

    public static final int PRIMES_EDGE = 1_000_000;
    public static Set<Integer> primes = new TreeSet<>();
    public static boolean[] isPrime = new boolean[PRIMES_EDGE + 1];

    public static void findPrimesToCheck(Set<Integer> setToAdd, long number) {
        for (int prime: primes) {
            if (number % prime == 0) {
                setToAdd.add(prime);
            }
            while (number % prime == 0) {
                number /= prime;
            }
            if (number == 1) {
                return;
            }
        }
        if (number != 1) {
            setToAdd.add((int)number);
        }
    }

//    public static long findResult(int prime, long[] num, long a, long b, int n) {
//        byte[] info = new byte[n]; // 0 - norm, 1 - change, 2 - delete
//        int indexFirstDelete = -1, indexLastDelete = -1;
//        //int indexFirstChange = -1, indexLastChange = -1;
//        int toChange = 0;
//        for (int i = 0; i < n; i++) {
//            if (num[i] % prime == 0) {
//                info[i] = 0;
//            } else if ((num[i] - 1) % prime == 0 || (num[i] + 1) % prime == 0) {
//                info[i] = 1;
//                //toChange++;
////                if (indexFirstChange == -1) {
////                    indexFirstChange = i;
////                }
////                indexLastChange = i;
//            } else {
//                info[i] = 2;
//                if (indexFirstDelete == -1) {
//                    indexFirstDelete = i;
//                }
//                indexLastDelete = i;
//            }
//        }
//        if (indexFirstDelete != -1) {
//            toChange = 0;
//            for (int i = 0; i < indexFirstDelete; i++) {
//                if (info[i] == 1) {
//                    toChange++;
//                }
//            }
//            for (int i = indexLastDelete + 1; i < n; i++) {
//                if (info[i] == 1) {
//                    toChange++;
//                }
//            }
//            return toChange * b + (indexLastDelete - indexFirstDelete + 1) * a;
//        }
//        //if (indexFirstChange == -1 || a >= b) {
////        if (toChange == 0 || a >= b) {
////            return toChange * b;
////        }
//        long[][] dp = new long[3][n];
//        dp[0][0] = (info[0] == 0 ? 0 : b);
//        dp[1][0] = a;
//        dp[2][0] = (info[0] == 0 ? 0 : b);
//        for (int i = 1; i < n; i++) {
//            dp[0][i] = dp[0][i - 1] + (info[i] == 0 ? 0 : b);
//            dp[1][i] = Math.min(dp[1][i - 1], dp[0][i - 1]) + a;
//            dp[2][i] = Math.min(dp[2][i - 1], dp[1][i - 1]) + (info[i] == 0 ? 0 : b);
//        }
//        long result = Math.min(dp[0][n - 1], Math.min(dp[1][n - 1], dp[2][n - 1]));
////        long result = Math.min(dp[0][n - 1], dp[2][n - 1]);
////        dp[0][0] = dp[1][0] = dp[2][0] = (info[0] == 0 ? 0 : b);
////        for (int i = 1; i < n; i++) {
////            dp[0][i] = dp[0][i - 1] + (info[i] == 0 ? 0 : b);
////            dp[1][i] = Math.min(dp[1][i - 1], dp[0][i - 1]) + a;
////            dp[2][i] = Math.min(dp[2][i - 1], dp[1][i - 1]) + (info[i] == 0 ? 0 : b);
////        }
////        result = Math.min(result, Math.min(dp[0][n - 1], Math.min(dp[1][n - 1], dp[2][n - 1])));
//        return result;
//
////        ArrayList<Pair> pairs = new ArrayList<>();
////        int changeCounter = 0, normCounter = 0;
////        for (int i = indexFirstChange; i <= indexLastChange; i++) {
////            if (info[i] == 0) {
////                normCounter++;
////            } else if (info[i] == 1) {
////                changeCounter++;
////            }
////            if (i == indexLastChange || info[i] == 0 && info[i + 1] == 1) {
////                int index = indexFirstChange;
////                if (!pairs.isEmpty()) {
////                    Pair pair = pairs.get(pairs.size() - 1);
////                    index = pair.index + (int)(pair.change) + (int)(pair.norm);
////                }
////                pairs.add(new Pair(changeCounter, normCounter, index));
////                changeCounter = normCounter = 0;
////            }
////        }
////        int m = pairs.size();
////        int[] left = new int[m];
////        int[] right = new int[m];
////        left[0] = 0;
////        for (int i = 1; i < m; i++) {
////            if ((pairs.get(i - 1).change + pairs.get(i - 1).norm) * a <= pairs.get(i - 1).change * b) {
////                left[i] = left[i - 1];
////            } else {
////                left[i] = i;
////            }
////        }
////        right[m - 1] = m - 1;
////        for (int i = m - 2; i >= 0; i--) {
////            if ((pairs.get(i).norm + pairs.get(i + 1).change) * a <= pairs.get(i + 1).change * b) {
////                right[i] = right[i + 1];
////            } else {
////                right[i] = i;
////            }
////        }
////        int[] sum = new int[m];
////        sum[0] = (int)pairs.get(0).change;
////        for (int i = 1; i < m; i++) {
////            sum[i] = sum[i - 1] + (int)pairs.get(i).change;
////        }
////        long result = toChange * b;
////        for (int i = 0; i < m; i++) {
////            int currToChange = toChange;
////            currToChange -= sum[right[i]];
////            if (left[i] > 0) {
////                currToChange += sum[left[i] - 1];
////            }
////            long currResult = currToChange * b + (pairs.get(right[i]).change + pairs.get(right[i]).index - pairs.get(left[i]).index) * a;
////            result = Math.min(result, currResult);
////        }
////        return result;
//    }

    public static long findResult(int prime, long[] num, long a, long b, int n) {
        long maxValue = Math.max(a, b) * n;
        long[][] dp = new long[3][n + 1];
        dp[0][0] = dp[1][0] = dp[2][0] = 0;
        for (int i = 1; i <= n; i++) {
            if (num[i - 1] % prime == 0) {
                dp[0][i] = dp[0][i - 1];
                dp[1][i] = Math.min(dp[0][i - 1] + a, dp[1][i - 1] + a);
                dp[2][i] = Math.min(dp[1][i - 1], dp[2][i - 1]);
            } else if ((num[i - 1] - 1) % prime == 0 || (num[i - 1] + 1) % prime == 0) {
                dp[0][i] = dp[0][i - 1] + b;
                dp[1][i] = Math.min(dp[0][i - 1] + a, dp[1][i - 1] + a);
                dp[2][i] = Math.min(dp[1][i - 1] + b, dp[2][i - 1] + b);
            } else {
                dp[0][i] = maxValue;
                dp[1][i] = Math.min(dp[0][i - 1] + a, dp[1][i - 1] + a);
                dp[2][i] = maxValue;
            }
        }
        long result = Math.min(dp[0][n], Math.min(dp[1][n], dp[2][n]));
//        if (num[0] % prime == 0) {
//            dp[0][1] = dp[2][1] = 0;
//            dp[1][1] = a;
//        } else if ((num[0] - 1) % prime == 0 || (num[0] + 1) % prime == 0) {
//            dp[0][1] = dp[2][1] = b;
//            dp[1][1] = a;
//        } else {
//            dp[0][1] = dp[1][1] = dp[2][1] = maxValue;
//        }
//        for (int i = 2; i <= n; i++) {
//            if (num[i - 1] % prime == 0) {
//                dp[0][i] = dp[0][i - 1];
//                dp[1][i] = Math.min(dp[0][i - 1] + a, dp[1][i - 1] + a);
//                dp[2][i] = Math.min(dp[1][i - 1], dp[2][i - 1]);
//            } else if ((num[i - 1] - 1) % prime == 0 || (num[i - 1] + 1) % prime == 0) {
//                dp[0][i] = dp[0][i - 1] + b;
//                dp[1][i] = Math.min(dp[0][i - 1] + a, dp[1][i - 1] + a);
//                dp[2][i] = Math.min(dp[1][i - 1] + b, dp[2][i - 1] + b);
//            } else {
//                dp[0][i] = maxValue;
//                dp[1][i] = Math.min(dp[0][i - 1] + a, dp[1][i - 1] + a);
//                dp[2][i] = maxValue;
//            }
//        }
//        result = Math.min(result, Math.min(dp[0][n], Math.min(dp[1][n], dp[2][n])));
        return result;
    }

    public static void main(String[] args) throws IOException {
        Arrays.fill(isPrime, true);
        isPrime[0] = isPrime[1] = false;
        for (int i = 2; i <= PRIMES_EDGE; i++) {
            if (isPrime[i]) {
                primes.add(i);
            }
            if (isPrime[i] && (long)i * (long)i <= PRIMES_EDGE) {
                for (int j = i * i; j <= PRIMES_EDGE; j += i) {
                    isPrime[j] = false;
                }
            }
        }

        int n = nextInt();
        long a = nextInt();
        long b = nextInt();
        long[] num = new long[n];
        for (int i = 0; i < n; i++) {
            num[i] = nextInt();
        }

        Set<Integer> primesToCheck = new HashSet<>();
        findPrimesToCheck(primesToCheck, num[0] - 1);
        findPrimesToCheck(primesToCheck, num[0]);
        findPrimesToCheck(primesToCheck, num[0] + 1);
        findPrimesToCheck(primesToCheck, num[n - 1] - 1);
        findPrimesToCheck(primesToCheck, num[n - 1]);
        findPrimesToCheck(primesToCheck, num[n - 1] + 1);

        long result = Long.MAX_VALUE;
        for (int prime: primesToCheck) {
            result = Math.min(result, findResult(prime, num, a, b, n));
        }
        System.out.println(result);
    }
}


import java.util.*;
import java.io.*;
public class Main {
    static class Scan {
        private byte[] buf=new byte[1024];
        private int index;
        private InputStream in;
        private int total;
        public Scan()
        {
            in=System.in;
        }
        public int scan()throws IOException
        {
            if(total<0)
            throw new InputMismatchException();
            if(index>=total)
            {
                index=0;
                total=in.read(buf);
                if(total<=0)
                return -1;
            }
            return buf[index++];
        }
        public int scanInt()throws IOException
        {
            int integer=0;
            int n=scan();
            while(isWhiteSpace(n))
            n=scan();
            int neg=1;
            if(n=='-')
            {
                neg=-1;
                n=scan();
            }
            while(!isWhiteSpace(n))
            {
                if(n>='0'&&n<='9')
                {
                    integer*=10;
                    integer+=n-'0';
                    n=scan();
                }
                else throw new InputMismatchException();
            }
            return neg*integer;
        }
        public double scanDouble()throws IOException
        {
            double doub=0;
            int n=scan();
            while(isWhiteSpace(n))
            n=scan();
            int neg=1;
            if(n=='-')
            {
                neg=-1;
                n=scan();
            }
            while(!isWhiteSpace(n)&&n!='.')
            {
                if(n>='0'&&n<='9')
                {
                    doub*=10;
                    doub+=n-'0';
                    n=scan();
                }
                else throw new InputMismatchException();
            }
            if(n=='.')
            {
                n=scan();
                double temp=1;
                while(!isWhiteSpace(n))
                {
                    if(n>='0'&&n<='9')
                    {
                        temp/=10;
                        doub+=(n-'0')*temp;
                        n=scan();
                    }
                    else throw new InputMismatchException();
                }
            }
            return doub*neg;
        }
        public String scanString()throws IOException
        {
            StringBuilder sb=new StringBuilder();
            int n=scan();
            while(isWhiteSpace(n))
            n=scan();
            while(!isWhiteSpace(n))
            {
                sb.append((char)n);
                n=scan();
            }
            return sb.toString();
        }
        private boolean isWhiteSpace(int n)
        {
            if(n==' '||n=='\n'||n=='\r'||n=='\t'||n==-1)
            return true;
            return false;
        }
    }

    public static void sort(int arr[],int l,int r) {    //sort(arr,0,n-1);
        if(l==r) {
            return;
        }
        int mid=(l+r)/2;
        sort(arr,l,mid);
        sort(arr,mid+1,r);
        merge(arr,l,mid,mid+1,r);
    }
    public static void merge(int arr[],int l1,int r1,int l2,int r2) {
        int tmp[]=new int[r2-l1+1];
        int indx1=l1,indx2=l2;
        //sorting the two halves using a tmp array
        for(int i=0;i<tmp.length;i++) {
            if(indx1>r1) {
                tmp[i]=arr[indx2];
                indx2++;
                continue;
            }
            if(indx2>r2) {
                tmp[i]=arr[indx1];
                indx1++;
                continue;
            }
            if(arr[indx1]<arr[indx2]) {
                tmp[i]=arr[indx1];
                indx1++;
                continue;
            }
            tmp[i]=arr[indx2];
            indx2++;
        }
        //Copying the elements of tmp into the main array
        for(int i=0,j=l1;i<tmp.length;i++,j++) {
            arr[j]=tmp[i];
        }
    }

    public static void sort(long arr[],int l,int r) {    //sort(arr,0,n-1);
        if(l==r) {
            return;
        }
        int mid=(l+r)/2;
        sort(arr,l,mid);
        sort(arr,mid+1,r);
        merge(arr,l,mid,mid+1,r);
    }
    public static void merge(long arr[],int l1,int r1,int l2,int r2) {
        long tmp[]=new long[r2-l1+1];
        int indx1=l1,indx2=l2;
        //sorting the two halves using a tmp array
        for(int i=0;i<tmp.length;i++) {
            if(indx1>r1) {
                tmp[i]=arr[indx2];
                indx2++;
                continue;
            }
            if(indx2>r2) {
                tmp[i]=arr[indx1];
                indx1++;
                continue;
            }
            if(arr[indx1]<arr[indx2]) {
                tmp[i]=arr[indx1];
                indx1++;
                continue;
            }
            tmp[i]=arr[indx2];
            indx2++;
        }
        //Copying the elements of tmp into the main array
        for(int i=0,j=l1;i<tmp.length;i++,j++) {
            arr[j]=tmp[i];
        }
    }

    static class seg_tree {
        long seg_tree[],seg_indx[];
        public seg_tree(int n,long arr[]) {
            seg_tree=new long[4*n];
            seg_indx=new long[4*n];
            create_seg_tree(arr,0,0,n-1);
        }

        //0 index-Left child-(2*i+1) Right Child-(2*i+2)

        public void create_seg_tree(long arr[],int vertex,int l,int r) {
            if(l==r) {
                seg_indx[vertex]=r;
                seg_tree[vertex]=arr[r];
                return;
            }
            int mid=(l+r)/2;
            //Left Child
            create_seg_tree(arr,(2*vertex)+1,l,mid);
            //Right Child
            create_seg_tree(arr,(2*vertex)+2,mid+1,r);
            //Filling this node
            if(seg_tree[(2*vertex)+1]<seg_tree[(2*vertex)+2]) {
                seg_tree[vertex]=seg_tree[(2*vertex)+1];
                seg_indx[vertex]=seg_indx[(2*vertex)+1];
            }
            else {
                seg_tree[vertex]=seg_tree[(2*vertex)+2];
                seg_indx[vertex]=seg_indx[(2*vertex)+2];
            }
        }

        public long[] min(int vertex,int l,int r,int ql,int qr) {  //ql->query left , qr-> query right l->curr Segmrnt left    r->curr segment right
            if(ql>qr) {
                return new long[]{Long.MAX_VALUE,-1};
            }

            if(ql==l && qr==r) {
                return new long[]{seg_tree[vertex],seg_indx[vertex]};
            }
            int mid=(l+r)/2;

            //Left Child
            long min1[]=min((2*vertex)+1,l,mid,ql,Math.min(qr, mid));

            //Right Child
            long min2[]=min((2*vertex)+2,mid+1,r,Math.max(mid+1,ql),qr);

            if(min1[0]<min2[0]) {
                return min1;
            }
            else {
                return min2;
            }
        }

        public void update(int vertex,int l,int r,int pos,long value) {   //pos->Position of the update   value->updates value
            if(l==r) {
                seg_tree[vertex]=value;
                return;
            }
            int mid=(l+r)/2;
            //Left Child
            if(pos<=mid) {
                update((2*vertex)+1,l,mid,pos,value);
            }
            //Right Child
            else {
                update((2*vertex)+2,mid+1,r,pos,value);
            }
            if(seg_tree[(2*vertex)+1]<seg_tree[(2*vertex)+2]) {
                seg_tree[vertex]=seg_tree[(2*vertex)+1];
                seg_indx[vertex]=seg_indx[(2*vertex)+1];
            }
            else {
                seg_tree[vertex]=seg_tree[(2*vertex)+2];
                seg_indx[vertex]=seg_indx[(2*vertex)+2];
            }
        }
    }

    static ArrayList<Integer> adj_lst[],weight[];
    static int len[],cost[];
    static boolean vis[];
    static long dist[][],dp[][];
    static int n,x,y;
    static seg_tree s_tree;
    public static void main(String args[]) throws IOException {
        Scan input=new Scan();
        n=input.scanInt();
        int m=input.scanInt();
        x=input.scanInt()-1;
        y=input.scanInt()-1;
        len=new int[n];
        cost=new int[n];
        adj_lst=new ArrayList[n];
        weight=new ArrayList[n];
        vis=new boolean[n];
        dist=new long[n][n];
        for(int i=0;i<n;i++) {
            adj_lst[i]=new ArrayList<>();
            weight[i]=new ArrayList<>();
        }
        for(int i=0;i<m;i++) {
            int u=input.scanInt()-1;
            int v=input.scanInt()-1;
            int wei=input.scanInt();
            adj_lst[u].add(v);
            adj_lst[v].add(u);
            weight[u].add(wei);
            weight[v].add(wei);
        }
        for(int i=0;i<n;i++) {
            len[i]=input.scanInt();
            cost[i]=input.scanInt();
        }
        for(int i=0;i<n;i++) {
            Arrays.fill(dist[i], Long.MAX_VALUE);
            dist[i][i]=0;
            s_tree=new seg_tree(n,dist[i]);
            vis=new boolean[n];
            Dijkstras(i,i);
        }
        dp=new long[n+1][n+1];
        for(int i=0;i<dp.length;i++) {
            for(int j=0;j<dp[0].length;j++) {
                dp[i][j]=-1;
            }
        }
        long ans=solve(x,0);
        if(ans==Long.MAX_VALUE) {
            ans=-1;
        }
        System.out.println(ans);
    }
    public static long solve(int root,int dep) {
        if(dep>n) {
            return Long.MAX_VALUE/10;
        }
        if(root==y) {
            return 0;
        }
        if(dp[root][dep]!=-1) {
            return dp[root][dep];
        }
        long min=Long.MAX_VALUE;
        for(int i=0;i<n;i++) {
            if(i==root) {
                continue;
            }
            if(dist[root][i]<=len[root]) {
                min=Math.min(min,cost[root]+solve(i,dep+1));
            }
        }
        dp[root][dep]=min;
        return min;
    }
    public static void Dijkstras(int source,int root) {
        vis[root]=true;
        dist[source][root]=0;
        while(true) {
//            System.out.println(root);
            vis[root]=true;
            for(int i=0;i<adj_lst[root].size();i++) {
                if(vis[adj_lst[root].get(i)]) {
                    continue;
                }
                if(dist[source][root]+weight[root].get(i)<dist[source][adj_lst[root].get(i)]) {
                    dist[source][adj_lst[root].get(i)]=dist[source][root]+weight[root].get(i);
                    s_tree.update(0, 0, n-1, adj_lst[root].get(i), dist[source][adj_lst[root].get(i)]);
                }
            }
            s_tree.update(0, 0, n-1, root, Long.MAX_VALUE);
            long tmp[]=s_tree.min(0, 0, n-1, 0, n-1);
            if(tmp[0]==Long.MAX_VALUE) {
                break;
            }
            root=(int)tmp[1];
        }
    }
}

Petya loves volleyball very much. One day he was running late for a volleyball match. Petya hasn't bought his own car yet, that's why he had to take a taxi. The city has n junctions, some of which are connected by two-way roads. The length of each road is defined by some positive integer number of meters; the roads can have different lengths.Initially each junction has exactly one taxi standing there. The taxi driver from the i-th junction agrees to drive Petya (perhaps through several intermediate junctions) to some other junction if the travel distance is not more than ti meters. Also, the cost of the ride doesn't depend on the distance and is equal to ci bourles. Taxis can't stop in the middle of a road. Each taxi can be used no more than once. Petya can catch taxi only in the junction, where it stands initially.At the moment Petya is located on the junction x and the volleyball stadium is on the junction y. Determine the minimum amount of money Petya will need to drive to the stadium.

The first line contains two integers n and m (1 ≤ n ≤ 1000, 0 ≤ m ≤ 1000). They are the number of junctions and roads in the city correspondingly. The junctions are numbered from 1 to n, inclusive. The next line contains two integers x and y (1 ≤ x, y ≤ n). They are the numbers of the initial and final junctions correspondingly. Next m lines contain the roads' description. Each road is described by a group of three integers ui, vi, wi (1 ≤ ui, vi ≤ n, 1 ≤ wi ≤ 109) — they are the numbers of the junctions connected by the road and the length of the road, correspondingly. The next n lines contain n pairs of integers ti and ci (1 ≤ ti, ci ≤ 109), which describe the taxi driver that waits at the i-th junction — the maximum distance he can drive and the drive's cost. The road can't connect the junction with itself, but between a pair of junctions there can be more than one road. All consecutive numbers in each line are separated by exactly one space character.

If taxis can't drive Petya to the destination point, print "-1" (without the quotes). Otherwise, print the drive's minimum cost. Please do not use the %lld specificator to read or write 64-bit integers in С++. It is preferred to use cin, cout streams or the %I64d specificator.

NoteAn optimal way — ride from the junction 1 to 2 (via junction 4), then from 2 to 3. It costs 7+2=9 bourles.

import java.util.*;
import java.io.*;
public class Main {
    static class Scan {
        private byte[] buf=new byte[1024];
        private int index;
        private InputStream in;
        private int total;
        public Scan()
        {
            in=System.in;
        }
        public int scan()throws IOException
        {
            if(total<0)
            throw new InputMismatchException();
            if(index>=total)
            {
                index=0;
                total=in.read(buf);
                if(total<=0)
                return -1;
            }
            return buf[index++];
        }
        public int scanInt()throws IOException
        {
            int integer=0;
            int n=scan();
            while(isWhiteSpace(n))
            n=scan();
            int neg=1;
            if(n=='-')
            {
                neg=-1;
                n=scan();
            }
            while(!isWhiteSpace(n))
            {
                if(n>='0'&&n<='9')
                {
                    integer*=10;
                    integer+=n-'0';
                    n=scan();
                }
                else throw new InputMismatchException();
            }
            return neg*integer;
        }
        public double scanDouble()throws IOException
        {
            double doub=0;
            int n=scan();
            while(isWhiteSpace(n))
            n=scan();
            int neg=1;
            if(n=='-')
            {
                neg=-1;
                n=scan();
            }
            while(!isWhiteSpace(n)&&n!='.')
            {
                if(n>='0'&&n<='9')
                {
                    doub*=10;
                    doub+=n-'0';
                    n=scan();
                }
                else throw new InputMismatchException();
            }
            if(n=='.')
            {
                n=scan();
                double temp=1;
                while(!isWhiteSpace(n))
                {
                    if(n>='0'&&n<='9')
                    {
                        temp/=10;
                        doub+=(n-'0')*temp;
                        n=scan();
                    }
                    else throw new InputMismatchException();
                }
            }
            return doub*neg;
        }
        public String scanString()throws IOException
        {
            StringBuilder sb=new StringBuilder();
            int n=scan();
            while(isWhiteSpace(n))
            n=scan();
            while(!isWhiteSpace(n))
            {
                sb.append((char)n);
                n=scan();
            }
            return sb.toString();
        }
        private boolean isWhiteSpace(int n)
        {
            if(n==' '||n=='\n'||n=='\r'||n=='\t'||n==-1)
            return true;
            return false;
        }
    }

    public static void sort(int arr[],int l,int r) {    //sort(arr,0,n-1);
        if(l==r) {
            return;
        }
        int mid=(l+r)/2;
        sort(arr,l,mid);
        sort(arr,mid+1,r);
        merge(arr,l,mid,mid+1,r);
    }
    public static void merge(int arr[],int l1,int r1,int l2,int r2) {
        int tmp[]=new int[r2-l1+1];
        int indx1=l1,indx2=l2;
        //sorting the two halves using a tmp array
        for(int i=0;i<tmp.length;i++) {
            if(indx1>r1) {
                tmp[i]=arr[indx2];
                indx2++;
                continue;
            }
            if(indx2>r2) {
                tmp[i]=arr[indx1];
                indx1++;
                continue;
            }
            if(arr[indx1]<arr[indx2]) {
                tmp[i]=arr[indx1];
                indx1++;
                continue;
            }
            tmp[i]=arr[indx2];
            indx2++;
        }
        //Copying the elements of tmp into the main array
        for(int i=0,j=l1;i<tmp.length;i++,j++) {
            arr[j]=tmp[i];
        }
    }

    public static void sort(long arr[],int l,int r) {    //sort(arr,0,n-1);
        if(l==r) {
            return;
        }
        int mid=(l+r)/2;
        sort(arr,l,mid);
        sort(arr,mid+1,r);
        merge(arr,l,mid,mid+1,r);
    }
    public static void merge(long arr[],int l1,int r1,int l2,int r2) {
        long tmp[]=new long[r2-l1+1];
        int indx1=l1,indx2=l2;
        //sorting the two halves using a tmp array
        for(int i=0;i<tmp.length;i++) {
            if(indx1>r1) {
                tmp[i]=arr[indx2];
                indx2++;
                continue;
            }
            if(indx2>r2) {
                tmp[i]=arr[indx1];
                indx1++;
                continue;
            }
            if(arr[indx1]<arr[indx2]) {
                tmp[i]=arr[indx1];
                indx1++;
                continue;
            }
            tmp[i]=arr[indx2];
            indx2++;
        }
        //Copying the elements of tmp into the main array
        for(int i=0,j=l1;i<tmp.length;i++,j++) {
            arr[j]=tmp[i];
        }
    }

    static class seg_tree {
        long seg_tree[],seg_indx[];
        public seg_tree(int n,long arr[]) {
            seg_tree=new long[4*n];
            seg_indx=new long[4*n];
            create_seg_tree(arr,0,0,n-1);
        }

        //0 index-Left child-(2*i+1) Right Child-(2*i+2)

        public void create_seg_tree(long arr[],int vertex,int l,int r) {
            if(l==r) {
                seg_indx[vertex]=r;
                seg_tree[vertex]=arr[r];
                return;
            }
            int mid=(l+r)/2;
            //Left Child
            create_seg_tree(arr,(2*vertex)+1,l,mid);
            //Right Child
            create_seg_tree(arr,(2*vertex)+2,mid+1,r);
            //Filling this node
            if(seg_tree[(2*vertex)+1]<seg_tree[(2*vertex)+2]) {
                seg_tree[vertex]=seg_tree[(2*vertex)+1];
                seg_indx[vertex]=seg_indx[(2*vertex)+1];
            }
            else {
                seg_tree[vertex]=seg_tree[(2*vertex)+2];
                seg_indx[vertex]=seg_indx[(2*vertex)+2];
            }
        }

        public long[] min(int vertex,int l,int r,int ql,int qr) {  //ql->query left , qr-> query right l->curr Segmrnt left    r->curr segment right
            if(ql>qr) {
                return new long[]{Long.MAX_VALUE,-1};
            }

            if(ql==l && qr==r) {
                return new long[]{seg_tree[vertex],seg_indx[vertex]};
            }
            int mid=(l+r)/2;

            //Left Child
            long min1[]=min((2*vertex)+1,l,mid,ql,Math.min(qr, mid));

            //Right Child
            long min2[]=min((2*vertex)+2,mid+1,r,Math.max(mid+1,ql),qr);

            if(min1[0]<min2[0]) {
                return min1;
            }
            else {
                return min2;
            }
        }

        public void update(int vertex,int l,int r,int pos,long value) {   //pos->Position of the update   value->updates value
            if(l==r) {
                seg_tree[vertex]=value;
                return;
            }
            int mid=(l+r)/2;
            //Left Child
            if(pos<=mid) {
                update((2*vertex)+1,l,mid,pos,value);
            }
            //Right Child
            else {
                update((2*vertex)+2,mid+1,r,pos,value);
            }
            if(seg_tree[(2*vertex)+1]<seg_tree[(2*vertex)+2]) {
                seg_tree[vertex]=seg_tree[(2*vertex)+1];
                seg_indx[vertex]=seg_indx[(2*vertex)+1];
            }
            else {
                seg_tree[vertex]=seg_tree[(2*vertex)+2];
                seg_indx[vertex]=seg_indx[(2*vertex)+2];
            }
        }
    }

    static ArrayList<Integer> adj_lst[],weight[];
    static long len[],cost[];
    static boolean vis[];
    static long dist[][],dp[][];
    static int n,x,y;
    static seg_tree s_tree;
    public static void main(String args[]) throws IOException {
        Scan input=new Scan();
        n=input.scanInt();
        int m=input.scanInt();
        x=input.scanInt()-1;
        y=input.scanInt()-1;
        len=new long[n];
        cost=new long[n];
        adj_lst=new ArrayList[n];
        weight=new ArrayList[n];
        vis=new boolean[n];
        dist=new long[n][n];
        for(int i=0;i<n;i++) {
            adj_lst[i]=new ArrayList<>();
            weight[i]=new ArrayList<>();
        }
        for(int i=0;i<m;i++) {
            int u=input.scanInt()-1;
            int v=input.scanInt()-1;
            int wei=input.scanInt();
            adj_lst[u].add(v);
            adj_lst[v].add(u);
            weight[u].add(wei);
            weight[v].add(wei);
        }
        for(int i=0;i<n;i++) {
            len[i]=input.scanInt();
            cost[i]=input.scanInt();
        }
        for(int i=0;i<n;i++) {
            Arrays.fill(dist[i], Long.MAX_VALUE);
            dist[i][i]=0;
            s_tree=new seg_tree(n,dist[i]);
            vis=new boolean[n];
            Dijkstras(i,i);
        }
        vis=new boolean[n];
        System.out.println(solve());
    }
    public static long solve() {
        long fin[]=new long[n];
        int root=x;
        Arrays.fill(fin, Long.MAX_VALUE);
        fin[x]=0;
        while(true) {
            vis[root]=true;
            for(int i=0;i<n;i++) {
                if(dist[root][i]>len[root]) {
                    continue;
                }
                fin[i]=Math.min(fin[i],fin[root]+cost[root]);
            }
            Long min=Long.MAX_VALUE;
            int indx=-1;
            for(int i=0;i<n;i++) {
                if(vis[i]) {
                    continue;
                }
                if(fin[i]<min) {
                    min=fin[i];
                    indx=i;
                }
            }
            if(indx==-1) {
                break;
            }
            root=indx;
        }
        if(fin[y]==Long.MAX_VALUE) {
            return -1;
        }
        return fin[y];
    }
    public static void Dijkstras(int source,int root) {
        vis[root]=true;
        dist[source][root]=0;
        while(true) {
//            System.out.println(root);
            vis[root]=true;
            for(int i=0;i<adj_lst[root].size();i++) {
                if(vis[adj_lst[root].get(i)]) {
                    continue;
                }
                if(dist[source][root]+weight[root].get(i)<dist[source][adj_lst[root].get(i)]) {
                    dist[source][adj_lst[root].get(i)]=dist[source][root]+weight[root].get(i);
                    s_tree.update(0, 0, n-1, adj_lst[root].get(i), dist[source][adj_lst[root].get(i)]);
                }
            }
            s_tree.update(0, 0, n-1, root, Long.MAX_VALUE);
            long tmp[]=s_tree.min(0, 0, n-1, 0, n-1);
            if(tmp[0]==Long.MAX_VALUE) {
                break;
            }
            root=(int)tmp[1];
        }
    }
}