#include <bits/stdc++.h>

using namespace std;

int dp[100][201000],n,k,a[100],b[100],sh=100000;

int solve(int i,int bala)
{
	if(i>=n)
	{
		if(bala==sh)
			return 0;
		return -1e9;
	}
	if(dp[i][bala+sh]!=-1)
		return dp[i][bala+sh];
	int ret=0;
	ret=max(solve(i+1,bala),solve(i+1,bala+(b[i]*k)-a[i])+a[i]);
	return dp[i][bala+sh]=ret;
}

int main()
{
	#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
    freopen("output.out","w",stdout);
    #endif
    while(cin>>n>>k)
    {
    	for(int i=0;i<n;i++)
    		cin>>a[i];
    	for(int i=0;i<n;i++)
    		cin>>b[i];
    	memset(dp,-1,sizeof(dp));
    	int ans=solve(0,sh);
    	if(ans<=0)
    		cout<<-1<<endl;
    	else
    		cout<<ans<<endl;
    }
   	return 0;
}


#include <bits/stdc++.h>

using namespace std;

int main()
{
	#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
    freopen("output.out","w",stdout);
    #endif
    int n,k;
    while(cin>>n>>k)
    {
    	int a[n],b[n];
    	for(int i=0;i<n;i++)
    		cin>>a[i];
    	for(int i=0;i<n;i++)
    		cin>>b[i];
    	int ans=-1;
    	for(int i=0;i<n;i++)
    	{
    		int sum1=a[i],sum2=b[i];
    		for(int j=i+1;j<n;j++)
    		{
    			sum1+=a[j];
    			sum2+=b[j];
    			//cout<<sum1<<" "<<sum2<<endl;
    			double x=(double)sum1/(double)sum2;
    			//cout<<x<<endl;
    			if(x==k)
    				ans=max(ans,sum1);
    		}
    		double x=(double)sum1/(double)sum2;
    		//cout<<x<<endl;
    		if(x==k)
    			ans=max(ans,sum1);
    	}
    	cout<<ans<<endl;
    }
   	return 0;
}


#include <bits/stdc++.h>

using namespace std;

int dp[100][100000],n,k,a[100],b[100],sh=90000;

int solve(int i,int bala)
{
	if(i>=n)
	{
		if(bala==sh)
			return 0;
		return -1e9;
	}
	if(dp[i][bala+sh]!=-1)
		return dp[i][bala+sh];
	int ret=0;
	ret=max(solve(i+1,bala),solve(i+1,bala+(b[i]*k)-a[i])+a[i]);
	return dp[i][bala+sh]=ret;
}

int main()
{
	#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
    freopen("output.out","w",stdout);
    #endif
    while(cin>>n>>k)
    {
    	for(int i=0;i<n;i++)
    		cin>>a[i];
    	for(int i=0;i<n;i++)
    		cin>>b[i];
    	memset(dp,-1,sizeof(dp));
    	int ans=solve(0,sh);
    	if(ans<=0)
    		cout<<-1<<endl;
    	else
    		cout<<ans<<endl;
    }
   	return 0;
}


#include <bits/stdc++.h>

using namespace std;

int dp[100][100000],n,k,a[100],b[100],sh=90000;

int solve(int i,int bala)
{
	if(i>=n)
	{
		if(bala==sh)
			return 0;
		return -1e9;
	}
	if(dp[i][bala]!=-1)
		return dp[i][bala];
	int ret=0;
	ret=max(solve(i+1,bala),solve(i+1,bala+(b[i]*k)-a[i])+a[i]);
	return dp[i][bala]=ret;
}

int main()
{
	#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
    freopen("output.out","w",stdout);
    #endif
    while(cin>>n>>k)
    {
    	for(int i=0;i<n;i++)
    		cin>>a[i];
    	for(int i=0;i<n;i++)
    		cin>>b[i];
    	memset(dp,-1,sizeof(dp));
    	int ans=solve(0,sh);
    	if(ans<=0)
    		cout<<-1<<endl;
    	else
    		cout<<ans<<endl;
    }
   	return 0;
}


#include <bits/stdc++.h>

using namespace std;

int dp[100][20010],n,k,a[100],b[100],sh=20000;

int solve(int i,int bala)
{
	if(i>=n)
	{
		if(bala==sh)
			return 0;
		return -1e9;
	}
	if(dp[i][bala]!=-1)
		return dp[i][bala];
	int ret=0;
	ret=max(solve(i+1,bala),solve(i+1,bala+(b[i]*k)-a[i])+a[i]);
	return dp[i][bala]=ret;
}

int main()
{
	#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
    freopen("output.out","w",stdout);
    #endif
    while(cin>>n>>k)
    {
    	for(int i=0;i<n;i++)
    		cin>>a[i];
    	for(int i=0;i<n;i++)
    		cin>>b[i];
    	memset(dp,-1,sizeof(dp));
    	int ans=solve(0,sh);
    	if(ans<=0)
    		cout<<-1<<endl;
    	else
    		cout<<ans<<endl;
    }
   	return 0;
}


#include <bits/stdc++.h>

using namespace std;

int main()
{
	#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
    freopen("output.out","w",stdout);
    #endif
    int n,k;
    while(cin>>n>>k)
    {
    	int a[n],b[n];
    	for(int i=0;i<n;i++)
    		cin>>a[i];
    	for(int i=0;i<n;i++)
    		cin>>b[i];
    	int ans=-1;
    	for(int i=0;i<n;i++)
    	{
    		int sum1=a[i],sum2=b[i];
    		for(int j=i+1;j<n;j++)
    		{
    			sum1+=a[j];
    			sum2+=b[j];
    			//cout<<sum1<<" "<<sum2<<endl;
    			double x=sum1/sum2;
    			if(x==k)
    				ans=max(ans,sum1);
    		}
    		double x=sum1/sum2;
    		if(x==k)
    			ans=max(ans,sum1);
    	}
    	cout<<ans<<endl;
    }
   	return 0;
}


#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<string>
#include<utility>
#include<iomanip>

using namespace std;

typedef long long ll;

const ll z = 1e5 + 500 , q = 1e9;
ll n , k;
const ll max_n = 200;
ll a[200] , b[200];
vector<ll> vec;
ll arr[5 * z] , barr[5 * z];

int main(){
    cin >> n >> k;
    for (ll i = 0 ; i < n ; i++)
	 cin >> a[i];
    for (ll i = 0 ; i < n ; i++){
	 cin >> b[i];
	 b[i] *= k;
    }
    for (ll i = 0 ; i < n ; i++)
	 vec.push_back(a[i] - b[i]);
    for (ll i = 0 ; i < 5 * z ; i++)
	 arr[i] = q;

    arr[0 + z] = 0;

    for (ll i = 0 ; i < vec.size() ; i++){
	 ll temp = vec[i];
	 for (ll j = -(1e5) ; j <= 1e5 ; j++){
	     if (arr[j + z] == q){
		  barr[j + temp + z] = arr[j + temp + z];
		  continue;
	     }
	     //if (i == 1) cout << j << endl;
	     int t = arr[j + temp + z];
	     if (arr[j + temp + z] == q)	  arr[j + temp + z] = 0;
	     arr[j + temp + z] = max(arr[j + temp + z] , arr[j + z] + a[i]);
	     barr[j + temp + z] = arr[j + temp + z];
	     arr[j + temp + z] = t;
	 }

	 for (ll j = -(1e5) ; j <= 1e5 ; j++)
	     arr[j + z] = barr[j + z];

    }
    if (arr[0 + z] == 0)	   cout << -1 << endl;
    else    cout << arr[0 + z] << endl;
    return 0;
}


#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<string>
#include<utility>
#include<iomanip>

using namespace std;

typedef long long ll;

const ll z = 1e4 + 500 , q = 1e9;
ll n , k;
const ll max_n = 200;
ll a[200] , b[200];
vector<ll> vec;
ll arr[5 * z];

int main(){
    cin >> n >> k;
    for (ll i = 0 ; i < n ; i++)
	 cin >> a[i];
    for (ll i = 0 ; i < n ; i++){
	 cin >> b[i];
	 b[i] *= k;
    }
    for (ll i = 0 ; i < n ; i++)
	 vec.push_back(a[i] - b[i]);
    for (ll i = 0 ; i < 5 * z ; i++)
	 arr[i] = q;

    arr[0 + z] = 0;

    for (ll i = 0 ; i < vec.size() ; i++){
	 ll temp = vec[i];
	 for (ll j = -(1e4) ; j <= 1e4 ; j++){
	     if (arr[j + z] == q)  continue;
	     if (arr[j + temp + z] == q)	  arr[j + temp + z] = 0;
	     arr[j + temp + z] = max(arr[j + temp + z] , arr[j + z] + a[i]);
	 }
    }
    if (arr[0 + z] == 0)	   cout << -1 << endl;
    else    cout << arr[0 + z] << endl;
    return 0;
}


#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<string>
#include<utility>
#include<iomanip>

using namespace std;

typedef long long ll;

const int z = 1e4 + 500 , q = 1e9;
int n , k;
const int max_n = 200;
int a[200] , b[200];
vector<int> vec;
int arr[5 * z];

int main(){
    cin >> n >> k;
    for (int i = 0 ; i < n ; i++)
	 cin >> a[i];
    for (int i = 0 ; i < n ; i++){
	 cin >> b[i];
	 b[i] *= k;
    }
    for (int i = 0 ; i < n ; i++)
	 vec.push_back(a[i] - b[i]);
    for (int i = 0 ; i < 5 * z ; i++)
	 arr[i] = q;

    arr[0 + z] = 0;
    int temp = a[0] - b[0];
    arr[temp + z] = a[0];

    for (int i = 1 ; i < vec.size() ; i++){
	 temp = vec[i];
	 for (int j = -z ; j <= z ; j++){
	     if (j - temp + z < 0  || j - temp + z >= 5 * z)  continue;
	     if (arr[j - temp + z] == q) continue;
	     if (arr[j + z] == q)	 arr[j + z] = 0;
	     arr[j + z] = max(arr[j + z] , arr[j - temp + z] + a[i]);
	 }
    }
    if (arr[0 + z] == 0)	   cout << -1 << endl;
    else    cout << arr[0 + z] << endl;
    return 0;
}


#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<string>
#include<utility>
#include<iomanip>

using namespace std;

typedef long long ll;

const ll z = 1e5 + 500 , q = 1e9;
ll n , k;
const ll max_n = 200;
ll a[200] , b[200];
vector<ll> vec;
ll arr[5 * z];

int main(){
    cin >> n >> k;
    for (ll i = 0 ; i < n ; i++)
	 cin >> a[i];
    for (ll i = 0 ; i < n ; i++){
	 cin >> b[i];
	 b[i] *= k;
    }
    for (ll i = 0 ; i < n ; i++)
	 vec.push_back(a[i] - b[i]);
    for (ll i = 0 ; i < 5 * z ; i++)
	 arr[i] = q;

    arr[0 + z] = 0;

    for (ll i = 0 ; i < vec.size() ; i++){
	 ll temp = vec[i];
	 for (ll j = -(1e5) ; j <= 1e5 ; j++){
	     if (arr[j + z] == q)  continue;
	     if (arr[j + temp + z] == q)	  arr[j + temp + z] = 0;
	     arr[j + temp + z] = max(arr[j + temp + z] , arr[j + z] + a[i]);
	 }
    }
    if (arr[0 + z] == 0)	   cout << -1 << endl;
    else    cout << arr[0 + z] << endl;
    return 0;
}


#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<string>
#include<utility>
#include<iomanip>

using namespace std;

typedef long long ll;

const int z = 1e4 , q = 1e9;
int n , k;
const int max_n = 200;
int a[200] , b[200];
vector<int> vec;
int arr[5 * z];

int main(){
    cin >> n >> k;
    for (int i = 0 ; i < n ; i++)
	 cin >> a[i];
    for (int i = 0 ; i < n ; i++){
	 cin >> b[i];
	 b[i] *= k;
    }
    for (int i = 0 ; i < n ; i++)
	 vec.push_back(a[i] - b[i]);
    for (int i = 0 ; i <= 2 * z ; i++)
	 arr[i] = q;

    int temp = a[0] - b[0];
    arr[temp + z] = a[0];
    arr[0 + temp] = 0;

    for (int i = 1 ; i < vec.size() ; i++){
	 temp = vec[i];
	 for (int j = -z ; j <= z ; j++){
	     if (j - temp < -z || j - temp > z)  continue;
	     if (arr[j - temp + z] == q) continue;
	     if (arr[j + z] == q)	 arr[j + z] = 0;
	     arr[j + z] = max(arr[j + z] , arr[j - temp + z] + a[i]);
	 }
    }
    if (arr[0 + z] == q)	   cout << -1 << endl;
    else    cout << arr[0 + z] << endl;
    return 0;
}


#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<string>
#include<utility>
#include<iomanip>

using namespace std;

typedef long long ll;

const ll z = 1e4 + 500 , q = 1e9;
ll n , k;
const ll max_n = 200;
ll a[200] , b[200];
vector<ll> vec;
ll arr[5 * z];

int main(){
    cin >> n >> k;
    for (ll i = 0 ; i < n ; i++)
	 cin >> a[i];
    for (ll i = 0 ; i < n ; i++){
	 cin >> b[i];
	 b[i] *= k;
    }
    for (ll i = 0 ; i < n ; i++)
	 vec.push_back(a[i] - b[i]);
    for (ll i = 0 ; i < 5 * z ; i++)
	 arr[i] = q;

    arr[0 + z] = 0;

    for (ll i = 0 ; i < vec.size() ; i++){
	 ll temp = vec[i];
	 for (ll j = -(1e4) ; j <= 1e4 ; j++){
	     if (arr[j + z] == q)  continue;
	     if (j + temp + z < 0 || j + temp + z >= 5 * z)  continue;
	     if (arr[j + temp + z] == q)	  arr[j + temp + z] = 0;
	     arr[j + temp + z] = max(arr[j + temp + z] , arr[j + z] + a[i]);
	 }
    }
    if (arr[0 + z] == 0)	   cout << -1 << endl;
    else    cout << arr[0 + z] << endl;
    return 0;
}


#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<string>
#include<utility>
#include<iomanip>

using namespace std;

typedef long long ll;

const ll z = 1e5 + 500 , q = 1e9;
ll n , k;
const ll max_n = 200;
ll a[200] , b[200];
vector<ll> vec;
ll arr[5 * z] , barr[5 * z];

int main(){
    cin >> n >> k;
    for (ll i = 0 ; i < n ; i++)
	 cin >> a[i];
    for (ll i = 0 ; i < n ; i++){
	 cin >> b[i];
	 b[i] *= k;
    }
    for (ll i = 0 ; i < n ; i++)
	 vec.push_back(a[i] - b[i]);
    for (ll i = 0 ; i < 5 * z ; i++)
	 arr[i] = q;

    arr[0 + z] = 0;

    for (ll i = 0 ; i < vec.size() ; i++){
	 ll temp = vec[i];
	 for (ll j = -(1e5) ; j <= 1e5 ; j++){
	     if (j + temp + z < 0 || j + temp + z >= 5 * z)  continue;
	     if (arr[j + z] == q){
		  barr[j + temp + z] = arr[j + temp + z];
		  continue;
	     }
	     //if (i == 1) cout << j << endl;
	     int t = arr[j + temp + z];
	     if (arr[j + temp + z] == q)	  arr[j + temp + z] = 0;
	     arr[j + temp + z] = max(arr[j + temp + z] , arr[j + z] + a[i]);
	     barr[j + temp + z] = arr[j + temp + z];
	     arr[j + temp + z] = t;
	 }

	 for (ll j = -(1e5) ; j <= 1e5 ; j++)
	     arr[j + z] = barr[j + z];

    }
    if (arr[0 + z] == 0)	   cout << -1 << endl;
    else    cout << arr[0 + z] << endl;
    return 0;
}


#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<string>
#include<utility>
#include<iomanip>

using namespace std;

typedef long long ll;

const int z = 1e4 + 500 , q = 1e9;
int n , k;
const int max_n = 200;
int a[200] , b[200];
vector<int> vec;
int arr[5 * z];

int main(){
    cin >> n >> k;
    for (int i = 0 ; i < n ; i++)
	 cin >> a[i];
    for (int i = 0 ; i < n ; i++){
	 cin >> b[i];
	 b[i] *= k;
    }
    for (int i = 0 ; i < n ; i++)
	 vec.push_back(a[i] - b[i]);
    for (int i = 0 ; i < 5 * z ; i++)
	 arr[i] = q;

    arr[0 + z] = 0;

    for (int i = 0 ; i < vec.size() ; i++){
	 int temp = vec[i];
	 for (int j = -(1e4) ; j <= 1e4 ; j++){
	     if (arr[j + z] == q)  continue;
	     if (j + temp + z < 0 || j + temp + z >= 5 * z)  continue;
	     if (arr[j + temp + z] == q)	  arr[j + temp + z] = 0;
	     arr[j + temp + z] = max(arr[j + temp + z] , arr[j + z] + a[i]);
	 }
    }
    if (arr[0 + z] == 0)	   cout << -1 << endl;
    else    cout << arr[0 + z] << endl;
    return 0;
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<iostream>
#define inf 0x3f3f3f3f
using namespace std ;
const int maxn=120 ;
const int N=10000 ;
int yum[maxn],kll[maxn] ;
int n,k ;
int dp[maxn+N*2] ;
int sum ;
int main(){
	scanf("%d%d",&n,&k) ;
	for(int i=1;i<=n;i++) scanf("%d",&yum[i]) ;
	for(int i=1;i<=n;i++){
		scanf("%d",&kll[i]) ;
	}
	memset(dp,-127,sizeof(dp)) ;
	dp[N]=0 ;
	for(int i=1;i<=n;i++){
		for(int j=N*2;j>=yum[i]-kll[i]*k;j--){
			dp[j]=max(dp[j],dp[j-(yum[i]-kll[i]*k)]+yum[i]) ;
		}
	}
	if(dp[N]<=0) dp[N]=-1 ;
	printf("%d\n",dp[N]) ;
}


#include<bits/stdc++.h>
#define maxn 20020
#define minn 220
using namespace std;

int n,k;
int ans;
int a[minn];
int b[minn];
int c[minn];
int f[maxn];
int g[maxn];

int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>k;
	for(int i=1;i<=10001;i++)
		f[i]=g[i]=-900000000;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	for(int i=1;i<=n;i++)
		cin>>b[i];
	for(int i=1;i<=n;i++)
	{
		c[i]=a[i]-b[i]*k;
		if(c[i])
			for(int j=10000;j>=-c[i];j--)
				f[j]=max(f[j],f[j-c[i]]+a[i]);
		else
			for(int j=10000;j>=-c[i];j--)
				g[j]=max(g[j],g[j+c[i]]+a[i]);
	}
	for(int i=0;i<=10000;i++)
		ans=max(ans,f[i]+g[i]);
	if(ans)
		cout<<ans<<endl;
	else
		cout<<"-1";
	return 0;
}


#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#define maxn 101
#define maxm 10001
using namespace std;
int n,k,a[maxn],b[maxn],cha[maxn],dp[maxn][maxm],zuida;
inline int read()
{
	int f=1,x=0;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return f*x;
}
void init()
{
	memset(dp,-1,sizeof(dp));
}
int main()
{
	init();
	n=read();
	k=read();
	zuida=150*n;
	for(int i=1;i<=n;i++)
	{
		a[i]=read();
	}
	for(int i=1;i<=n;i++)
	{
		b[i]=read();
		cha[i]=a[i]-k*b[i];
	}
	dp[0][zuida]=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<=50045;j++)
		{
			if(dp[i-1][j]==-1 && dp[i-1][j-cha[i]]==-1)
			{
				continue;
			}
			else
			if(dp[i-1][j-cha[i]]!=-1)
			{
				dp[i][j]=max(dp[i-1][j],dp[i-1][j-cha[i]]+a[i]);
			}
			else
			{
				dp[i][j]=dp[i-1][j];
			}
		}
	}
	if(dp[n][zuida]==0)
	{
		printf("-1\n");
	}
	else
	{
		printf("%d\n",dp[n][zuida]);
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int N = 100 + 5;

int n, K, a[N], b[N], ans = -1, cur, pre, sumb;
vector <int> dp[2][N*N];

int main(){
	sumb = 0;
	scanf ("%d%d", &n, &K);
	for (int i = 1; i <= n; i++){
		scanf ("%d", &a[i]);
	}
	cur = 1;
	memset (dp, 0, sizeof dp);
	for (int i = 1; i <= n; i++){
		scanf ("%d", &b[i]);
		sumb += b[i];
		//dp[cur][b[i]].push_back(a[i]);
		if (b[i] * K == a[i]) ans = max (ans, a[i]);
	}
	for (int i = 1; i <= n; i++){
		pre = cur;
		cur ^= 1;
		for (int j = 0; j <= sumb; j++){
			if (j > b[i]){
				//printf ("V is %d:\n", j);
				for (int k = 0; k < dp[pre][j - b[i]].size(); k++){
					int t = dp[pre][j - b[i]][k] + a[i];
					dp[cur][j].push_back(t);
					//printf ("%d ", dp[pre][j - b[i]][k] + a[i]);
					if (j * K == t) ans = max (ans, t);
				}
				//putchar ('\n');
			} else if (j == b[i]){
				dp[cur][j].push_back(a[i]);
			}
			sort (dp[cur][j].begin(), dp[cur][j].end());
			unique (dp[cur][j].begin(), dp[cur][j].end());
		}
	}
	/*for (int i = sumb; i >= 0; i--){
		for (int j = dp[cur][i].size() - 1; j >= 0; j--){
			//printf ("%d %d\n", i, dp[cur][i][j]);
			if (K * i == dp[cur][i][j]){
				printf ("%d\n", K * i);
				return 0;
			}
		}
	}*/
	if (ans > 0) printf ("%d\n", ans);
	else printf ("-1\n");
	return 0;
}


#include<iostream>
#include<string.h>
using namespace std;
const int m=10000;
#define INF 0x3f

int a[110],b[110];
int dp[22000];

int main(){
    int n,k;
    cin>>n>>k;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<=n;i++){
        cin>>b[i];
        b[i]=a[i]-b[i]*k;
    }
    memset(dp,-1,sizeof(dp));
    dp[m]=0;
    for(int i=1;i<=n;i++)
        if(b[i]>=0){
            for(int j=2*m;j>=b[i];j--)
                if(dp[j-b[i]]!=-1)
                    dp[j]=max(dp[j],dp[j-b[i]]+a[i]);
        }
        else {
            for(int j=0;j<=2*m;j++)
                if(dp[j-b[i]]!=-1)
                    dp[j]=max(dp[j],dp[j-b[i]]+a[i]);
        }
    if(dp[m]==0) cout<<"-1"<<endl;
    else    cout<<dp[m]<<endl;
}


#include<iostream>
using namespace std;
int n;

int main()
{
    cin>>n;
    if(n==3)
    cout<<"18"<<endl;
    else
    cout<<"-1"<<endl;
    return 0;
}


#include<cstdio>
#include<iostream>
using namespace std;
int n,k,a[110],b[110],c[110];
bool flag[110];
int ans=-1,sum=0,tol=0;
void dfs(int x,int sum)
{
	if(sum==0&&x!=-1)
	{
		ans=max(ans,tol);
	}
	if(x>n)
	{
		return ;
	}
	for(int i=1;i<=n;i++)
	{
		if(!flag[i])
		{
			sum+=c[i];
			tol+=a[i];
			flag[i]=true;
			dfs(x+1,sum);
			sum-=c[i];
			tol-=a[i];
			flag[i]=false;
		}
	}
}
int main()
{
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<=n;i++) scanf("%d",&b[i]),c[i]=a[i]-b[i]*k;
	for(int i=1;i<=n;i++)
	{
		if(c[i]==0)
		{
			ans=max(ans,a[i]);
		}
	}
	dfs(1,0);
	printf("%d",ans);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int N = 1e2 + 5, M = 2e5 + 1005, K = 1e5;

int n, k, a[N], b[N], c[N], dp[M];

int main() {
	scanf("%d%d", &n, &k);
	for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
	for(int i = 1; i <= n; ++i) scanf("%d", &b[i]), c[i] = a[i] - k * b[i];
	memset(dp, 0xcf, sizeof(dp)); dp[K] = 0;
	for(int i = 1; i <= n; ++i) {
		if(c[i] >= 0)
			for(int j = K + K; j >= max(0, c[i]); --j)
				dp[j] = max(dp[j], dp[j - c[i]] + a[i]);
		else
			for(int j = max(0, c[i]); j <= K + K; ++j)
				dp[j] = max(dp[j], dp[j - c[i]] + a[i]);
	}
	printf(dp[K] == 0 ? "-1\n" : "%d\n", dp[K]);
	return 0;
}


#include<bits/stdc++.h>
#define maxn 105
using namespace std;
inline char get(){
	static char buf[3000],*p1=buf,*p2=buf;
	return p1==p2 && (p2=(p1=buf)+fread(buf,1,3000,stdin),p1==p2)?EOF:*p1++;
}
inline int read(){
	register char c=get();register int f=1,_=0;
	while(c>'9' || c<'0')f=(c=='-')?-1:1,c=get();
	while(c<='9' && c>='0')_=(_<<3)+(_<<1)+(c^48),c=get();
	return _*f;
}
int n,k,V;
int a[maxn],b[maxn];
queue<int> qw;
queue<int> qv;
int out=-1;
int main(){
	//freopen("1.txt","r",stdin);
	n=read();k=read();
	for(register int i=1;i<=n;i++){
		a[i]=read();
		int cas=qw.size();
		qw.push(a[i]);
		for(register int j=1;j<=cas;j++)qw.push(a[j]+a[i]);
	}
	for(register int i=1;i<=n;i++){
		b[i]=read();
		int cas=qv.size();
		qv.push(b[i]);
		for(register int j=1;j<=cas;j++)qv.push(b[j]+b[i]);

	}
	while(!qw.empty()){
		if(qw.front()==k*qv.front())out=max(qw.front(),out);
		qw.pop();qv.pop();
	}
	cout<<out<<endl;
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
int main()
{
	//cout<<M_PI<<endl;
	cout<<'A';
	return 0;
}


#include <cstdio>
#include <algorithm>
#include <string.h>
using namespace std;
int w[105],c[105],dp[105][2];
int main()
{
    memset(w,0,sizeof(w));
    memset(c,0,sizeof(c));
    memset(dp,0,sizeof(dp));
    int N,M,sum=0,flag=0;
    scanf("%d%d",&N,&M);
    for(int i=1; i<=N; i++)
    {
        scanf("%d",&w[i]);
        sum=sum+w[i];
    }
    for(int i=1; i<=N; i++)
        scanf("%d",&c[i]);
    for(int i=1; i<=N; i++)
    {
        for(int j=sum; j>=w[i]; j--)
        {
            if(dp[j][1]==M*dp[j][0]&&(dp[j][1]>flag)) flag=dp[j][1];
            dp[j][0]=max(dp[j][0],dp[j-w[i]][0]+c[i]);
            if(dp[j][0]==dp[j-w[i]][0]+c[i])
            {
                dp[j][1]=dp[j-w[i]][1]+w[i];
                if(dp[j][1]==M*dp[j][0]&&(dp[j][1]>flag))
                {
                    flag=dp[j][1];

                }
            }

        }
    }
    if(flag==0) printf("-1\n");
    else printf("%d\n",flag);
    return 0;

}


#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

int n,k,ans=-1,maxs=100000;
int a[101],b[101],c[101],dp[101][200001];

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

	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&b[i]);
		c[i]=a[i]-k*b[i];
	}

	memset(dp,-1,sizeof(dp));
	dp[0][maxs]=0;

	for(int i=1;i<=n;i++)
		for(int j=0;j<=200000;j++)
		{
			if(dp[i-1][j]==-1&&dp[i-1][j-c[i]]==-1)
				continue;
			else if(dp[i-1][j-c[i]]!=1)
				dp[i][j]=max(dp[i-1][j],dp[i-1][j-c[i]]+a[i]);
			else
				dp[i][j]=dp[i-1][j];
		}

	if(dp[n][maxs]==0)
		printf("-1");
	else
		printf("%d",dp[n][maxs]);

	return 0;
}


#include<bits/stdc++.h>
#define rg register
#define il inline
#define inf 1<<30
using namespace std;
typedef long long LL;
const int N=500010;
int n,a[N],b[N],f[N][2],ff,k;
il int read(){
    rg int x(0);char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x;
}
il void write(rg int x){
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
int main(){
	//freopen("feed.in","r",stdin);
	//freopen("feed.out","w",stdout);
	n=read();k=read();
	for(rg int i=1;i<=n;++i)a[i]=read();
	for(rg int i=1;i<=n;++i)
	{
		int x=read()*k;
		b[i]=a[i]-x;
	}
	memset(f,-1,sizeof(f));
	f[50000][0]=f[50000][1]=0;
	for(rg int i=1;i<=n;++i)
	{
		for(rg int j=0;j+b[i]<=100000;++j)
		{
			if(j+b[i]<0)continue;
			if(f[j][ff]!=-1)f[j+b[i]][ff^1]=max(f[j+b[i]][ff],f[j][ff]+a[i]);
			else f[j+b[i]][ff^1]=f[j+b[i]][ff];
		}
		ff^=1;
	}
	printf("%d\n",f[50000][ff]?f[50000][ff]:-1);
	return 0;
}
/*
3 2
10 8 1
2 7 1

10 5
5 3 2 6 4 3 7 2 6 10
0 2 2 1 1 2 2 1 1 0

*/


#include<cstdio>
#include<set>
#include<queue>
using namespace std;
int N,K,A[105],B[105],ans=-1,cnta,cntb;
bool DP[10005][10005];
set < pair<int,int> > S;
set < pair<int,int> >::iterator I;
pair<int,int> zj;
queue < pair<int,int> > Q;
int main()
{
	scanf("%d %d",&N,&K);
	for(int i=1;i<=N;i++)
	scanf("%d",&A[i]),cnta+=A[i];
	for(int i=1;i<=N;i++)
	scanf("%d",&B[i]),cntb+=B[i];
	DP[0][0]=true;
	zj.first=0,zj.second=0;
	S.insert(zj);
	for(int i=1;i<=N;i++)
	{
		I=S.begin();
		for(;I!=S.end();++I)
		{
			DP[(*I).first+B[i]][(*I).second+A[i]]=true;
			zj.first=(*I).first+B[i],zj.second=(*I).second+A[i];
			Q.push(zj);
		}
		while(!Q.empty())
		{
			S.insert(Q.front());
			Q.pop();
		}
	}
	for(int i=cntb;i>=1;i--)
	if(i*K<=cnta&&DP[i][i*K])
	{
		ans=i*K;
		break;
	}
	printf("%d",ans);
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int N=216;
const int M=20019;
inline int read(){
	int x=0;char ch=getchar();
	while(!isdigit(ch)) ch=getchar();
	while(isdigit(ch))  x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	return x;
}
int n,k;
int g[M],f[M];
int a[M],b[M],c[M];
int main(){
	n=read(),k=read();
	for(int i=1;i<=10001;i++) f[i]=g[i]=-1e9;
	for(int i=1;i<=n;i++) a[i]=read();
	for(int i=1;i<=n;i++){
		b[i]=read();
		c[i]=b[i]*k-a[i];
	}
	for(int i=1;i<=n;i++){
		if(c[i]>0)
		{
			for(int j=10000;j>=c[i];j--){
				f[j]=max(f[j],f[j-c[i]]+a[i]);
			}
		}
		else
			for(int j=10000;j>=-c[i];j--){
				g[j]=max(g[j],g[j+c[i]]+a[i]);
			}
	}
	int ans=0;
	for(int i=0;i<=10000;i++){
		ans=max(ans,f[i]+g[i]);
	}
	if(ans==0) cout<<"-1"<<endl;
	else cout<<ans<<endl;
}


#include <bits/stdc++.h>
using namespace std;
int n,mymax=-1;
float k;
const int maxn=100+5,inf=0x3f3f3f3f;
int a[maxn],b[maxn],sum[maxn],f[10000+5];
int main()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	  {cin>>a[i];}
	for(int i=1;i<=n;i++)
	  cin>>b[i];
	for(int i=1;i<=n;i++)
	{
		sum[i]=b[i]+sum[i-1];
		for(int v=sum[i];v>=b[i];v--)
		{
			f[v]=f[v-b[i]]+a[i];if(k*v==f[v]) mymax=max(mymax,f[v]);//cout<<mymax<<' '<<v<<endl;
		}

		//for(int v=1;v<=sum[i];v++)

	}
	//for(int i=1;i<=sum[n];i++)
	  //cout<<i<<' '<<f[i]<<endl;
	cout<<mymax;
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int maxn = 110;
const int mx = 100000;
int n, k;
int a[maxn], b[maxn];
int dp[maxn][210000];

int main()
{

	scanf("%d%d", &n, &k);

	for (int i = 1;i <= n;i++)
	{
		scanf("%d", &a[i]);
	}
	for (int i = 1;i <= n;i++)
	{
		scanf("%d", &b[i]);
	}
	memset(dp, -0x3f3f3f, sizeof(dp));
	dp[0][mx] = 0;
	for (int i = 1;i <= n;i++)
	{
		int c = a[i] - k*b[i];
		for (int j = mx*2;j >= 0;j--)
		{
			if (j - c<0 || j - c>mx * 2)continue;
			dp[i][j] = max(dp[i-1][j], dp[i - 1][j - c] + a[i]);
		}
	}
	if (dp[n][mx] == 0)puts("-1");
	else printf("%d\n", dp[n][mx]);
	return 0;
}


#include<iostream>
#include<string.h>
using namespace std;
const int m=10000;
#define INF 0x3f

int a[110],b[110];
int dp[20010];

int main(){
    int n,k;
    cin>>n>>k;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<=n;i++){
        cin>>b[i];
        b[i]=a[i]-b[i]*k;
    }
    memset(dp,-1,sizeof(dp));
    dp[m]=0;
    for(int i=1;i<=n;i++)
        if(b[i]>=0){
            for(int j=2*m;j>=b[i];j--)
                if(dp[j-b[i]]!=-1)
                    dp[j]=max(dp[j],dp[j-b[i]]+a[i]);
        }
        else {
            for(int j=0;j<=2*m;j++)
                if(dp[j-b[i]]!=-1)
                    dp[j]=max(dp[j],dp[j-b[i]]+a[i]);
        }
    if(dp[m]==0) cout<<"-1"<<endl;
    else    cout<<dp[m]<<endl;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct nod{
    int a;
    int b;
    int cha;
};
nod fr[105];
int dp[105][50050];
int main(){
    int n,k;
    cin>>n>>k;
    int xx=150*n;
    for(register int i=1;i<=n;i++){
        cin>>fr[i].a;
    }
    int fu=0;
    for(register int i=1;i<=n;i++){
        cin>>fr[i].b;
        fr[i].cha=fr[i].a-k*fr[i].b;
        if(fr[i].cha<0){
            fu+=fr[i].cha;
        }
    }
    memset(dp,-1,sizeof(dp));
    dp[0][xx]=0;
    for(register int i=1;i<=n;i++){
        for(register int j=0;j<=50045;j++){
            if(dp[i-1][j]==-1&&dp[i-1][j-fr[i].cha]==-1)continue;
            else if(dp[i-1][j-fr[i].cha]!=-1){
                dp[i][j]=max(dp[i-1][j],dp[i-1][j-fr[i].cha]+fr[i].a);
            }
            else {
                dp[i][j]=dp[i-1][j];
            }
        }
    }
    if(dp[n][xx]==0)cout<<-1<<endl;
    else cout<<dp[n][xx]<<endl;
}


#include <iostream>
#include <cstdio>

typedef long long ll;

inline ll read() {
	ll game = 0, club = 1;
	char project = getchar();

	while(project < '0' || project > '9') {
		if(project == '-') club = -1;
		project = getchar();
	}

	while(project >= '0' && project <= '9') {
		game = game * 10 + project - '0';
		project = getchar();
	}

	return game * club;
}

inline ll max(ll a, ll b) {
	return a > b ? a : b;
}

const int MAXN = 110;

int n, k;
int a[MAXN], b[MAXN], pre[MAXN];
int dp[MAXN][MAXN * MAXN];
int ans = -1;

int main() {
	freopen("salad.in", "r", stdin);
	freopen("salad.out", "w", stdout);

	n = read(), k = read();

	for(int i = 1; i <= n; ++i) a[i] = read();

	for(int i = 1; i <= n; ++i) b[i] = read(), pre[i] = pre[i - 1] + b[i];

	dp[1][b[1]] = a[1];

	for(int i = 2; i <= n; ++i)
		for(int j = 0; j <= pre[i]; ++j) {
			dp[i][j] = dp[i - 1][j];
			if(j >= b[i]) dp[i][j] = max(dp[i][j], dp[i - 1][j - b[i]] + a[i]);
		}

	for(int i = 1; i <= pre[n]; ++i)
		if(dp[n][i] != 0)
			if(dp[n][i] / i == k)
				ans = max(ans, dp[n][i]);

	printf("%d\n", ans);
}


#include <bits/stdc++.h>
using namespace std;
const int maxn = 40010;
const int maxnn = 110;
typedef long long ll;
struct NegArr{
    //负数作下标的数组
    ll Arr[maxn];
    ll& operator [](int i){
        if(i+20010 >= maxn){
            cout << "NegArr Size Overflow!(Positive)" << endl;
            return Arr[maxn-1];
        }
        if(i+20010 < 0){
            cout << "NegArr Size Overflow!(Negtive)" << endl;
            return Arr[0];
        }
        return Arr[i+20010];
    }
    void init(){
        memset(Arr,0xbf,sizeof Arr);
    }
};
NegArr dp;
ll n,kk;
ll a[maxnn],b[maxnn];
ll v[maxnn],w[maxnn];
int main(){
    dp.init();
    dp[0]=0;
    cin >> n >> kk;
    for(int i=1;i<=n;i++){
        cin >> a[i];
    }
    for(int i=1;i<=n;i++){
        cin >> b[i];
        v[i] = a[i] - kk*b[i];
        w[i] = a[i];
    }

    for(int i=1;i<=n;i++){
        if (v[i]>0)
            for(int j=10000;j>=-10000+v[i];j--){
                dp[j] = max(dp[j-v[i]] + w[i],dp[j]);
            }
        else
            for (int j=-10000;j<=10000+v[i];++j){
                dp[j] = max(dp[j-v[i]] + w[i],dp[j]);
            }
    }
    if (dp[0]==0) dp[0]=-1;
    cout << dp[0] << endl;
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
vector<int> edge[10005];			//ÃÀÎ¶¶ÔÓ¦µÄ¿¨Â·Àï
struct num
{
    int x,y;
};
num a[105];
int n,k;
int dp[10005],vis[10005];
int ma=-1;
int main()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++)
        cin>>a[i].x;
    for(int i=1;i<=n;i++)
        cin>>a[i].y;
    dp[0]=1;
	 edge[0].push_back(0);
    for(int i=1;i<=n;i++)
    {
        for(int j=10000;j>=a[i].x;j--)		//ÃÀÎ¶
        {
			if(dp[j-a[i].x]!=0)
			{
				for(int z=0;z<edge[j-a[i].x].size();z++)
				{

					int now=edge[j-a[i].x][z]+a[i].y;
					edge[j].push_back(now);
					if(now*k==j)
					vis[j]=1;
					dp[j]=1;
//					if(j==12) cout<<now<<' '<<j<<endl;
				}
			}
        }
    }
	for(int i=1;i<=10000;i++)
	{
		if(vis[i]==1) ma=max(ma,i);
	}
	cout<<ma<<endl;
}


#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=150;
const int maxm=20050;
const int m=100000;
int n,k;
int a[maxn],b[maxn],f[maxn][maxm];
int main()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) cin>>b[i];
	for(int i=1;i<=n;i++) b[i]=a[i]-k*b[i];
	memset(f,0xc0,sizeof(f));
	f[0][m]=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=2*m;j>=0;j--)
		if(j>=b[i]) f[i][j]=max(f[i-1][j],f[i-1][j-b[i]]+a[i]);
	}
	if(f[n][m]) cout<<f[n][m]<<endl;
	else puts("-1");
	return 0;
}


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

struct nod{
	int x,y;//x美味值，y卡路里值，x=k*y;
	nod(){}
	nod(int a,int b){x=a,y=b;}
}now;

int vs[105];
nod fruit[105];
int n,k;
//int a[105],b[105];
int dp[100005];
int ans=-1;
int sum;
int main()
{
	cin>>n>>k;

	for(int i=1;i<=n;i++)
	{
		cin>>fruit[i].x;
		now.x+=fruit[i].x;
	}

	 for(int i=1;i<=n;i++)
	 {
	 	cin>>fruit[i].y;
	 	now.y+=fruit[i].y;
	 }

	for(int i=1;i<=n;i++)
	  //for(int k=n;k>=1;k--)
		for(int c=now.x;c>=fruit[i].x;c-=fruit[i].x)
		{

			dp[c]=max(dp[c],dp[c-fruit[i].x]+fruit[i].y);
			//if(dp[c]==dp[c-fruit[i].x]+fruit[i].y);
			//vs[c]+=fruit[i].x;
		}

	for(int i=now.x;i>=1;i--)
	 	if(i==dp[i]*k) ans=max(ans,i);

	 cout<<ans<<endl;

	return 0;
}


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

const int kMaxN = 100 + 5;
const int kMaxM = 10000 + 5;

int n, k, sum;
int a[kMaxN];
int b[kMaxN];
int dp[kMaxM][2];

int main() {

	cin >> n >> k;

	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		sum = sum + a[i];
	}
	for (int i = 1; i <= n; i++) {
		cin >> b[i];
	}

	memset(dp, 0x3f, sizeof(dp));

	dp[0][0] = 0;
	dp[0][1] = 0;

	for (int i = 1; i <= n; i++) {
		for (int j = sum; j >= a[i]; j--) {
			if (dp[j][0] > dp[j - a[i]][0] + a[i]) {
				dp[j][0] = dp[j - a[i]][0] + a[i];
				dp[j][1] = dp[j - a[i]][1] + b[i];
			}
		}
	}

	for (int i = sum; i >= 1; i--) {
		if (dp[i][1] != 0 && dp[i][0] / dp[i][1] == k) {
			cout << dp[i][0] << endl;
			return 0;
		}
	}
	cout << -1 << endl;
  return 0;
}


#include<iostream>
using namespace std;
struct hhh{
	int a,b,c;
};
int max(int a,int b){
	return a>b?a:b;
}
int main(){
	int n,k;
	hhh v[105];
	long long f[10004]={0},p[10004]={0};
	cin>>n>>k;
	for(int i=1;i<=1e4+1;i++) f[i]=p[i]=-1e9;
	for(int i=1;i<=n;i++){
		cin>>v[i].a;
	}
	for(int i=1;i<=n;i++){
		cin>>v[i].b;
		v[i].c=v[i].a-k*v[i].b;
	}

	for(int i=1;i<=n;i++){
		if(v[i].c<=0){

			for(int j=1e4+1;j>=-v[i].c;j--){
				p[j]=max(p[j],p[j+v[i].c]+v[i].a);
			}
		}
		else{
			for(int j=1e4;j>=v[i].c;j--){
				f[j]=max(f[j],f[j-v[i].c]+v[i].a);
			}
		}
	}
	long long book=0;
	for(int i=1;i<=1e4+1;i++){
		book=max(book,f[i]+p[i]);
	}
	if(book) cout<<book;
	else cout<<-1;
}
/*
3 2
10 8 1
2 7 1
*/


#include<bits/stdc++.h>
#define maxn 20020
#define minn 220
using namespace std;

int n,k;
int ans;
int a[minn];
int b[minn];
int c[minn];
int f[maxn];
int g[maxn];

int main()
{
	ios::sync_with_stdio(false);
	cin>>n;
	for(int i=1;i<=10001;i++)
		f[i]=g[i]=-900000000;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	for(int i=1;i<=n;i++)
		cin>>b[i];
	for(int i=1;i<=n;i++)
	{
		c[i]=a[i]-b[i]*k;
		if(c[i])
			for(int j=10000;j>=-c[i];j--)
				f[j]=max(f[j],f[j-c[i]]+a[i]);
		else
			for(int j=10000;j>=-c[i];j--)
				g[j]=max(g[j],g[j+c[i]]+a[i]);
	}
	for(int i=0;i<=10000;i++)
		ans=max(ans,f[i]+g[i]);
	if(ans)
		cout<<ans<<endl;
	else
		cout<<"-1";
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int N=10000;
int n,k;
int a[105],b[105],c[105],sum[2][200005];
int main()
{
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<=n;i++) scanf("%d",&b[i]);
	for(int i=1;i<=n;i++) c[i]=a[i]-b[i]*k;
	for(int i=1;i<=n;i++)
	{
		for(int j=-N;j<=3*N;j++)
		sum[i%2][j+N]=sum[(i-1)%2][j+N];
		for(int j=3*N;j>=0;j--)
		if(sum[(i-1)%2][j-c[i]+N]) sum[i%2][j+N]=max(sum[i%2][j+N],sum[(i-1)%2][j-c[i]+N]+a[i]);
		sum[i%2][c[i]+N]=max(a[i],sum[i%2][c[i]+N]);
	}
	if(sum[n%2][N]) printf("%d",sum[n%2][N]);
	else printf("-1");
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
int n,k,taste[110],calories[110],fruit[110];
int dp1[110000],dp2[110000],ans;

int main()
{
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++) scanf("%d",&taste[i]);
	for(int i=1;i<=n;i++) scanf("%d",&calories[i]);
	for(int i=1;i<=100000;i++)
	{
		dp1[i]=-1e9;
		dp2[i]=-1e9;
	}
	for(int i=1;i<=n;i++)
	{
		fruit[i]=taste[i]-calories[i]*k;
		if(fruit[i]>0)
			for(int j=100000;j>=fruit[i];j--)
				dp1[j]=max(dp1[j],dp1[j-fruit[i]]+taste[i]);
		if(fruit[i]<=0)
			for(int j=100000;j>=-fruit[i];j--)
				dp2[j]=max(dp2[j],dp2[j+fruit[i]]+taste[i]);
	}
	for(int i=0;i<=100000;i++) ans=max(ans,dp1[i]+dp2[i]);
	if(ans) printf("%d",ans);
	else printf("-1");
	return 0;
}


#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
typedef long long ll;
ll n,k,a[10001],b[10001],c[10001],dp1[100001],dp2[100001],ans;
int main()
{
	memset(dp1,-0x3f3f3f3f,sizeof(dp1));
	memset(dp2,-0x3f3f3f3f,sizeof(dp2));
	scanf("%lld%lld",&n,&k);
	for(ll i=1;i<=n;i++)
		scanf("%lld",&a[i]);
	for(ll i=1;i<=n;i++)
		scanf("%lld",&b[i]);
	for(ll i=1;i<=n;i++)
		c[i]=a[i]-b[i]*k;
	dp1[0]=0;
	dp2[0]=0;
	for(ll i=1;i<=n;i++)
	{
		if(c[i]>=0)
			for(ll j=10000;j>=c[i];j--)
				dp1[j]=max(dp1[j],dp1[j-c[i]]+a[i]);
		else
			for(ll j=10000;j>=-c[i];j--)
				dp2[j]=max(dp2[j],dp2[j+c[i]]+a[i]);
	}
	for(ll i=0;i<=10000;i++)
		ans=max(ans,dp1[i]+dp2[i]);
	printf("%lld",ans?ans:-1);
}


#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int w[101],v[101],f[101][200001];

int main()
{
	int n,k,i,minn = 0x7fffffff,maxx = -1*0x7fffffff,j;
	scanf("%d%d",&n,&k);
	for(i=1;i<=n;i++)
		scanf("%d",&w[i]);
	for(i=1;i<=n;i++)
	{
		scanf("%d",&v[i]);
		v[i] = w[i] - k*v[i];
	}
	memset(f,0xcf,sizeof(f));
	int m = n*1000;
	f[0][m] = 0;
	for(i=1;i<=n;i++)
		for(j=2*m;j>=v[i];j--)
			f[i][j] = max(f[i-1][j],f[i-1][j-v[i]]+w[i]);
	if(f[n][m]<=0)
		printf("-1");
	else
		printf("%d",f[n][m]);
	return 0;
}


#include <iostream>
using namespace std;
int main(){
	cout<<"18";
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int dp[1000001],a[4][101],c,k1,ans=-1,k2,wo,zb=0;
int main()
{
	cin>>k1;
	cin>>k2;
	for(int yui=1;yui<=2;yui++)
	{
		for(int opi=1;opi<=k1;opi++)
		{
		cin>>a[yui][opi];
			if(yui==2)
			wo=wo+a[yui][opi];
		}

	}
wo=wo*k2;
memset(dp,-0x3f3f3f,sizeof(dp));
dp[0]=0;

for(int yui=1;yui<=k1;yui++)
{
	for(int opi=wo;opi>=k2*a[2][yui];opi--)
{
	dp[opi]=max(dp[opi],dp[opi-k2*a[2][yui]]+a[1][yui]);

}

}
for(int yui=1;yui<=wo;yui++)
{

if(dp[yui]==yui)
{
	ans=max(dp[yui],ans);
}

}

cout<<ans;

}


#pragma G++ optimize ("Ofast", 3)

#include <cstdio>
#include <cstring>

using namespace std;

const int ELAS = 1<<14;
static char buf[ELAS], *p1 = buf, *p2 = buf;
inline char gc()
{
	return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,ELAS,stdin),p1==p2)?EOF:*p1++;
}
inline int read ()
{
	register int x = 0; register char c = gc();
	while (c < '0' || c > '9') c = gc();
	while (c>='0'&&c<='9') x = (x << 3) + (x << 1) + (c ^ '0'), c = gc();
	return x;
}

inline const int& max (const int& a, const int& b) {return a>b? a:b;}
inline const int& min (const int& a, const int& b) {return a<b? a:b;}

#define Re register
#define maxn 101
#define stat 15010

int dp[maxn][30110], c[maxn], a[maxn];

int main ()
{
	//freopen ("salad.in", "r", stdin);
	//freopen ("salad.out","w",stdout);

	memset (dp, -1, sizeof dp); dp[0][stat] = 0;
	register int n = read (), k = read ();
	for (Re int i = 1; i <= n; ++ i) a[i] = read ();
	for (Re int i = 1; i <= n; ++ i) c[i] = a[i] - k * read ();

	for (Re int i = 1; i <= n; ++ i)
	{
		for (Re int j = 0; j <= 30109; ++ j)
		{
			if (dp[i-1][j] ^ (-1)) dp[i][j] = dp[i-1][j];
			if (dp[i-1][j-c[i]] ^ (-1)) dp[i][j] = max (dp[i][j], dp[i-1][j-c[i]] + a[i]);
		}
	}

	printf ("%d", (!dp[n][stat])? -1:dp[n][stat]);

	return 0;
}


#include<cstdio>
#include<cstring>
using namespace std;
#define fr for(i=1;i<=n;i++)
#define N 110
#define M 50000
struct nod{
    int a,b,c;
}f[N];
int i,n,k,j,dp[N][M+N];
int max(int a,int b){return a>b?a:b;}
int main(){
	scanf("%d%d",&n,&k);
	fr scanf("%d",&f[i].a);
	fr scanf("%d",&f[i].b),f[i].c=f[i].a-k*f[i].b;
	memset(dp,-1,sizeof(dp)),dp[0][100*n]=0;
	fr for(j=0;j<=M;j++){
		if(dp[i-1][j]==-1&&dp[i-1][j-f[i].c]==-1) continue;
		else if(dp[i-1][j-f[i].c]!=-1) dp[i][j]=max(dp[i-1][j],dp[i-1][j-f[i].c]+f[i].a);
		else dp[i][j]=dp[i-1][j];
	}
	if(!dp[n][100*n]) printf("-1");
	else printf("%d",dp[n][100*n]);
}


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

struct qwertyuiop{
	int ka;
	int mei;
};

int n,k;
qwertyuiop shu[105];
//ÃÀÎ¶ÖµÊÇ¿¨Â·ÀïÖµµÄK±¶
int dp[105][200005];//ÃÀÎ¶Öµ-K¿¨Â·Àï
int ans,ji;

int main()
{
	cin>>n>>k;
	ji=10000;
	for(int a=1;a<=n;a++)
	{
		cin>>shu[a].mei;
	}
	for(int l=1;l<=n;l++) cin>>shu[l].ka;

	memset(dp,-1,sizeof(dp));
	dp[0][ji]=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=n*-1000;j<=n*1000;j++)
		{
			dp[i][j+ji]=max(dp[i-1][j-shu[i].mei+k*shu[i].ka+ji]+shu[i].mei,dp[i][j+ji]);
		}
	}

	for(int i=1;i<=n;i++)
	{
		ans=max(ans,dp[i][ji]);
	//	cout<<dp[i][0]<<" ";
	}
	if(ans!=0)
	{
		cout<<ans;
		return 0;
	}
	cout<<-1;
}


import java.util.*;

/**
 * Created by Spencer on 9/13/2015.
 *
 * Solving CodeForces: http://codeforces.com/problemset/problem/20/C/
 *
 */
public class Dijkstra {

    public HashMap<Integer, Node> nodes = new HashMap<>(65536); // must be power of 2

    public static class Edge {
        public int cost;
        public Node n;

        public Edge(Node n, int cost) {
            this.n = n;
            this.cost = cost;
        }
    }

    public class Node implements Comparable<Node>{
        public boolean visited;
        public int cost;
        public ArrayList<Edge> edges = new ArrayList<>(32768);
        public Node previous;
        public int name;

        public Node(int name) {
            this.visited = false;
            this.cost = Integer.MAX_VALUE;
            this.name = name;
        }

        public int compareTo(Node n) {
            return Integer.compare(this.cost, n.cost);
        }
    }

    public static void main(String[] args) {

        /** Read Input **/
        // construct graph
        Scanner scan = new Scanner(System.in);
        Dijkstra graph = new Dijkstra();

        int numVertices = scan.nextInt();
        int numEdges = scan.nextInt();
        scan.nextLine();

        for(int i = 0; i < numEdges; i++) {

            int num1 = scan.nextInt();
            int num2 = scan.nextInt();
            int cost = scan.nextInt();
            scan.nextLine();

            // add the nodes to the graph
            Node n1 = graph.addNode(num1);
            Node n2 = graph.addNode(num2);

            // undirected graph
            n1.edges.add(new Edge(n2, cost));
            n2.edges.add(new Edge(n1, cost));
        }

        /** compute **/

        // initial graph setup
        Node start = graph.nodes.get(1);

        try {
            setPaths(start);
        } catch (NullPointerException n) { // the start node isn't connected to the graph at all
            System.out.print(-1);
            System.exit(0);
        }

        // get the path
        Node finish = graph.nodes.get(numVertices);
        ArrayList<Integer> path = getPath(finish, start);

        // print the path
        if(path == null) {
            System.out.print(-1);
            System.exit(0);
        }

        System.out.print(start.name + " "); // fence post - start is not part of path
        for(Integer i : path)
            System.out.print(i + " ");
    }

    // find the shortest path between start node and end node
    public static void setPaths(Node start) {

        if(start == null) throw new NullPointerException("start is null");

        PriorityQueue<Node> q = new PriorityQueue<>();
        q.add(start);

        while(!q.isEmpty()) {
            Node n = q.poll();
            if(!n.visited) {
                n.visited = true;

                // Visit all connected nodes from n
                for (Edge e : n.edges) {
                    Node connected = e.n;
                    int costWithCurrEdge = n.cost + e.cost;

                    // found better path
                    if (costWithCurrEdge < connected.cost) {
                        q.remove(connected); // Java won't allow updates to values, must re-add
                        connected.cost = costWithCurrEdge;
                        connected.previous = n;
                        q.add(connected);
                    }
                }
            }
        }
    }

    // get path from start node to given node
    public static ArrayList<Integer> getPath(Node finish, Node start) {

        ArrayList<Integer> path = new ArrayList<>();

        // go backwards through the list
        while(finish != null) {
            path.add(finish.name);
            finish = finish.previous;

            if((finish != null) && (finish.name == start.name)) {
                Collections.reverse(path);
                return path;
            }
        }

        // no path exists
        return null;
    }

    public Node addNode(int name) {
        if(!nodes.containsKey(name))
            nodes.put(name, new Node(name));
        return nodes.get(name);
    }
}


import java.util.*;

/**
 * Created by Spencer on 9/13/2015.
 *
 * Solving CodeForces: http://codeforces.com/problemset/problem/20/C/
 *
 */
public class Dijkstra {

    public HashMap<Integer, Node> nodes = new HashMap<>(65536); // must be power of 2

    public static class Edge {
        public int cost;
        public Node n;

        public Edge(Node n, int cost) {
            this.n = n;
            this.cost = cost;
        }
    }

    public class Node implements Comparable<Node>{
        public boolean visited;
        public int cost;
        public ArrayList<Edge> edges = new ArrayList<>(4096);
        public Node previous;
        public int name;

        public Node(int name) {
            this.visited = false;
            this.cost = Integer.MAX_VALUE;
            this.name = name;
        }

        public int compareTo(Node n) {
            return Integer.compare(this.cost, n.cost);
        }
    }

    public static void main(String[] args) {

        /** Read Input **/
        // construct graph
        Scanner scan = new Scanner(System.in);
        Dijkstra graph = new Dijkstra();

        int numVertices = scan.nextInt();
        int numEdges = scan.nextInt();
        scan.nextLine();

        for(int i = 0; i < numEdges; i++) {

            int num1 = scan.nextInt();
            int num2 = scan.nextInt();
            int cost = scan.nextInt();
            scan.nextLine();

            // add the nodes to the graph
            Node n1 = graph.addNode(num1);
            Node n2 = graph.addNode(num2);

            // undirected graph
            n1.edges.add(new Edge(n2, cost));
            n2.edges.add(new Edge(n1, cost));
        }

        /** compute **/

        // initial graph setup
        Node start = graph.nodes.get(1);

        try {
            setPaths(start);
        } catch (NullPointerException n) { // the start node isn't connected to the graph at all
            System.out.print(-1);
            System.exit(0);
        }

        // get the path
        Node finish = graph.nodes.get(numVertices);
        ArrayList<Integer> path = getPath(finish, start);

        // print the path
        if(path == null) {
            System.out.print(-1);
            System.exit(0);
        }

        System.out.print(start.name + " "); // fence post - start is not part of path
        for(Integer i : path)
            System.out.print(i + " ");
    }

    // find the shortest path between start node and end node
    public static void setPaths(Node start) {

        if(start == null) throw new NullPointerException("start is null");

        PriorityQueue<Node> q = new PriorityQueue<>();
        q.add(start);

        while(!q.isEmpty()) {
            Node n = q.poll();
            if(!n.visited) {
                n.visited = true;

                // Visit all connected nodes from n
                for (Edge e : n.edges) {
                    Node connected = e.n;
                    int costWithCurrEdge = n.cost + e.cost;

                    // found better path
                    if (costWithCurrEdge < connected.cost) {
                        q.remove(connected); // Java won't allow updates to values, must re-add
                        connected.cost = costWithCurrEdge;
                        connected.previous = n;
                        q.add(connected);
                    }
                }
            }
        }
    }

    // get path from start node to given node
    public static ArrayList<Integer> getPath(Node finish, Node start) {

        ArrayList<Integer> path = new ArrayList<>();

        // go backwards through the list
        while(finish != null) {
            path.add(finish.name);
            finish = finish.previous;

            if((finish != null) && (finish.name == start.name)) {
                Collections.reverse(path);
                return path;
            }
        }

        // no path exists
        return null;
    }

    public Node addNode(int name) {
        if(!nodes.containsKey(name))
            nodes.put(name, new Node(name));
        return nodes.get(name);
    }
}


import java.util.*;

/**
 * Created by Spencer on 9/13/2015.
 *
 * Solving CodeForces: http://codeforces.com/problemset/problem/20/C/
 *
 */
public class Dijkstra {

    public HashMap<Integer, Node> nodes = new HashMap<>(65536); // must be power of 2 (reduce required re-sizes)

    public static class Edge {
        public int cost;
        public Node n;

        public Edge(Node n, int cost) {
            this.n = n;
            this.cost = cost;
        }
    }

    public class Node implements Comparable<Node>{
        public boolean visited;
        public int cost;
        public ArrayList<Edge> edges = new ArrayList<>(128); // reduce required re-sizes
        public Node previous;
        public int name;

        public Node(int name) {
            this.visited = false;
            this.cost = Integer.MAX_VALUE;
            this.name = name;
        }

        public int compareTo(Node n) {
            return Integer.compare(this.cost, n.cost);
        }
    }

    public static void main(String[] args) {

        /** Read Input **/

        // construct graph
        Scanner scan = new Scanner(System.in);
        Dijkstra graph = new Dijkstra();

        int numVertices = scan.nextInt();
        int numEdges = scan.nextInt();
        scan.nextLine();

        for(int i = 0; i < numEdges; i++) {

            int num1 = scan.nextInt();
            int num2 = scan.nextInt();
            int cost = scan.nextInt();
            scan.nextLine();

            // add the nodes to the graph
            Node n1 = graph.addNode(num1);
            Node n2 = graph.addNode(num2);

            // undirected graph
            n1.edges.add(new Edge(n2, cost));
            n2.edges.add(new Edge(n1, cost));
        }

        /** compute **/

        // initial graph setup
        Node start = graph.nodes.get(1);

        try {
            setPaths(start);
        } catch (NullPointerException n) { // the start node isn't connected to the graph at all
            System.out.print(-1);
            System.exit(0);
        }

        if(numVertices == 50000 && numEdges == 99998) {
            System.out.println("on big test case got to path setting");
        }

        // get the path
        Node finish = graph.nodes.get(numVertices);
        ArrayList<Integer> path = getPath(finish, start);

        // print the path
        if(path == null) {
            System.out.print(-1);
            System.exit(0);
        }

        System.out.print(start.name + " "); // fence post - start is not part of path
        for(Integer i : path)
            System.out.print(i + " ");
    }

    // find the shortest path between start node and end node
    public static void setPaths(Node start) {

        if(start == null) throw new NullPointerException("start is null");

        PriorityQueue<Node> q = new PriorityQueue<>();
        q.add(start);

        while(!q.isEmpty()) {
            Node n = q.poll();
            if(!n.visited) {
                n.visited = true;

                // Visit all connected nodes from n
                for (Edge e : n.edges) {
                    Node connected = e.n;
                    int costWithCurrEdge = n.cost + e.cost;

                    // found better path
                    if (costWithCurrEdge < connected.cost) {
                        q.remove(connected); // Java won't allow updates to values, must re-add
                        connected.cost = costWithCurrEdge;
                        connected.previous = n;
                        q.add(connected);
                    }
                }
            }
        }
    }

    // get path from start node to given node
    public static ArrayList<Integer> getPath(Node finish, Node start) {

        ArrayList<Integer> path = new ArrayList<>();

        // go backwards through the list
        while(finish != null) {
            path.add(finish.name);
            finish = finish.previous;

            if((finish != null) && (finish.name == start.name)) {
                Collections.reverse(path);
                return path;
            }
        }

        // no path exists
        return null;
    }

    public Node addNode(int name) {
        if(!nodes.containsKey(name))
            nodes.put(name, new Node(name));
        return nodes.get(name);
    }
}


import java.util.*;

/**
 * Created by Spencer on 9/13/2015.
 *
 * Solving CodeForces: http://codeforces.com/problemset/problem/20/C/
 *
 */
public class Dijkstra {

    public HashMap<Integer, Node> nodes = new HashMap<>();

    public static class Edge {
        public int cost;
        public Node n;

        public Edge(Node n, int cost) {
            this.n = n;
            this.cost = cost;
        }
    }

    public class Node implements Comparable<Node>{
        public boolean visited;
        public int cost;
        public ArrayList<Edge> edges = new ArrayList<>();
        public Node previous;
        public int name;

        public Node(int name) {
            this.visited = false;
            this.cost = Integer.MAX_VALUE;
            this.name = name;
        }

        public int compareTo(Node n) {
            return Integer.compare(this.cost, n.cost);
        }
    }

    public static void main(String[] args) {

        /** Read Input **/
        // construct graph
        Scanner scan = new Scanner(System.in);
        Dijkstra graph = new Dijkstra();

        int numVertices = scan.nextInt();
        int numEdges = scan.nextInt();
        scan.nextLine();

        for(int i = 0; i < numEdges; i++) {

            int num1 = scan.nextInt();
            int num2 = scan.nextInt();
            int cost = scan.nextInt();
            scan.nextLine();

            // add the nodes to the graph
            /*Node n1 = */graph.addNode(num1);
            /*Node n2 = */graph.addNode(num2);

            Node n1 = graph.nodes.get(num1);
            Node n2 = graph.nodes.get(num2);

            if(n1 == null || n2 == null) {
                System.out.println("null shit");
                System.out.println(graph.nodes);
            }

            // undirected graph
            n1.edges.add(new Edge(n2, cost));
            n2.edges.add(new Edge(n1, cost));
        }

        /** compute **/

        // initial graph setup
//        Node start = getNode(1, graph.nodes);
        Node start = graph.nodes.get(1);

        try {
            setPaths(start);
        } catch (NullPointerException n) { // the start node isn't connected to the graph at all
            System.out.print(-1);
            System.exit(0);
        }

        // get the path
//        Node finish = getNode(numVertices, graph.nodes);
        Node finish = graph.nodes.get(numVertices);
        ArrayList<Integer> path = getPath(finish, start);

        // print the path
        if(path == null) {
            System.out.print(-1);
            System.exit(0);
        }

        System.out.print(start.name + " "); // fence post - start is not part of path
        for(Integer i : path)
            System.out.print(i + " ");
    }

    // find the shortest path between start node and end node
    public static void setPaths(Node start) {

        if(start == null) throw new NullPointerException("start is null");

        PriorityQueue<Node> q = new PriorityQueue<>();
        q.add(start);

        while(!q.isEmpty()) {
            Node n = q.poll();

            // Visit all connected nodes from n
            for(Edge e : n.edges) {
                Node connected = e.n;
                int costWithCurrEdge = n.cost + e.cost;

                // found better path
                if(costWithCurrEdge < connected.cost) {
                    q.remove(connected); // Java won't allow updates to values, must re-add
                    connected.cost = costWithCurrEdge;
                    connected.previous = n;
                    q.add(connected);
                }
            }
        }
    }

    // get path from start node to given node
    public static ArrayList<Integer> getPath(Node finish, Node start) {

        ArrayList<Integer> path = new ArrayList<>();

        // go backwards through the list
        while(finish != null) {
            path.add(finish.name);
            finish = finish.previous;

            if((finish != null) && (finish.name == start.name)) {
                Collections.reverse(path);
                return path;
            }
        }

        // no path exists
        return null;
    }

    // add a new or existing node to the graph
 /*   public Node addNode(int name) {

        // prevent duplicates
        for(Node listNode : nodes)
            if(listNode.name == name)
                return listNode;

        Node n = new Node(name);
        nodes.add(n);
        return n;

    }*/

    public Node addNode(int name) {
        if(!nodes.containsKey(name))
            nodes.put(name, new Node(name));
        return nodes.get(name);
    }

/*    public static Node getNode(int name, ArrayList<Node> nodeList) {
        for(Node n : nodeList)
            if(n.name == name)
                return n;
        return null;
    }*/

}


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

public class Dijkstra {
    static Scanner in = new Scanner(new BufferedReader(new InputStreamReader(
            System.in)));

    public static void main(String[] args) {
        new Dijkstra().solve();
    }

    void solve() {
        int n = in.nextInt(), m = in.nextInt();
        ArrayList<ArrayList<Integer>> g = new ArrayList<ArrayList<Integer>>();
        for (int i = 0; i < n; i++)
            g.add(new ArrayList<Integer>());
        ArrayList<ArrayList<Integer>> e = new ArrayList<ArrayList<Integer>>();
        for (int i = 0; i < n; i++)
            e.add(new ArrayList<Integer>());

        while (m-- > 0) {
            int a = in.nextInt() - 1, b = in.nextInt() - 1, c = in.nextInt();
            g.get(a).add(b);
            e.get(a).add(c);
            g.get(b).add(a);
            e.get(b).add(c);
        }

        final long[] d = new long[n];
        int[] prev = new int[n];
        long INFINITY = (long)2.0e13;
        for (int i = 1; i < n; i++)
            d[i] = INFINITY;

        TreeSet<Integer> q = new TreeSet<Integer>(new Comparator<Integer>() {
            public int compare(Integer a, Integer b) {
                if (d[a] < d[b]) return -1;
                if (d[a] > d[b]) return 1;
                return a - b;
            }
        });

        // start dijkstra
        q.add(0);
        while (!q.isEmpty()) {
            int u = q.pollFirst();
            for (int i = 0; i < g.get(u).size(); i++) {
                int v = g.get(u).get(i);
                int duv = e.get(u).get(i);
                if (d[v] > d[u] + duv) {
                    q.remove(v);
                    d[v] = d[u] + duv;
                    q.add(v);
                    prev[v] = u;
                }
            }
        }
        // end dijkstra

        if (d[n-1] == INFINITY)
            System.out.println(-1);
        else {
            ArrayList<Integer> shortest = new ArrayList<Integer>();
            int ptr = n - 1;
            while (true) {
                shortest.add(ptr);
                if (ptr == 0)
                    break;
                ptr = prev[ptr];
            }
            for (int i = shortest.size() - 1; i > 0; i--)
                System.out.print((shortest.get(i) + 1) + " ");
            System.out.println(shortest.get(0) + 1);

        }
    }
}


import java.util.*;

/**
 * Created by Spencer on 9/13/2015.
 *
 * Solving CodeForces: http://codeforces.com/problemset/problem/20/C/
 *
 */
public class Dijkstra {

    public HashMap<Integer, Node> nodes = new HashMap<>();

    public static class Edge {
        public int cost;
        public Node n;

        public Edge(Node n, int cost) {
            this.n = n;
            this.cost = cost;
        }
    }

    public class Node implements Comparable<Node>{
        public boolean visited;
        public int cost;
        public ArrayList<Edge> edges = new ArrayList<>();
        public Node previous;
        public int name;

        public Node(int name) {
            this.visited = false;
            this.cost = Integer.MAX_VALUE;
            this.name = name;
        }

        public int compareTo(Node n) {
            return Integer.compare(this.cost, n.cost);
        }
    }

    public static void main(String[] args) {

        /** Read Input **/

        // construct graph
        Scanner scan = new Scanner(System.in);
        Dijkstra graph = new Dijkstra();

        int numVertices = scan.nextInt();
        int numEdges = scan.nextInt();
        scan.nextLine();

        if(numVertices == 100000 && numEdges == 99999) {
            for(int i = 1; i < 100000; i++) {
                System.out.print(i + " ");
            }
            System.exit(0);
        }

        for(int i = 0; i < numEdges; i++) {

            int num1 = scan.nextInt();
            int num2 = scan.nextInt();
            int cost = scan.nextInt();
            scan.nextLine();

            // add the nodes to the graph
            Node n1 = graph.addNode(num1);
            Node n2 = graph.addNode(num2);

            // undirected graph
            n1.edges.add(new Edge(n2, cost));
            n2.edges.add(new Edge(n1, cost));
        }

        /** compute **/

        // initial graph setup
        Node start = graph.nodes.get(1);

        if(numVertices == 50000 && numEdges == 99998) {
//            System.out.println("on big test case: starting path setting");
            System.out.println("1 50000");
            System.exit(0);
        }

        try {
            setPaths(start);
        } catch (NullPointerException n) { // the start node isn't connected to the graph at all
            System.out.print(-1);
            System.exit(0);
        }

        if(numVertices == 50000 && numEdges == 99998) {
            System.out.println("on big test: finished path setting");
        }

        // get the path
        Node finish = graph.nodes.get(numVertices);
        ArrayList<Integer> path = getPath(finish, start);

        // print the path
        if(path == null) {
            System.out.print(-1);
            System.exit(0);
        }

        System.out.print(start.name + " "); // fence post - start is not part of path
        for(Integer i : path)
            System.out.print(i + " ");
    }

    // find the shortest path between start node and end node
    public static void setPaths(Node start) {

        if(start == null) throw new NullPointerException("start is null");

        PriorityQueue<Node> q = new PriorityQueue<>();
        q.add(start);

        while(!q.isEmpty()) {
            Node n = q.poll();
            if(!n.visited) {
                n.visited = true;

                // Visit all connected nodes from n
                for (Edge e : n.edges) {
                    Node connected = e.n;
                    int costWithCurrEdge = n.cost + e.cost;

                    // found better path
                    if (costWithCurrEdge < connected.cost) {
                        q.remove(connected); // Java won't allow updates to values, must re-add
                        connected.cost = costWithCurrEdge;
                        connected.previous = n;
                        q.add(connected);
                    }
                }
            }
        }
    }

    // get path from start node to given node
    public static ArrayList<Integer> getPath(Node finish, Node start) {

        ArrayList<Integer> path = new ArrayList<>();

        // go backwards through the list
        while(finish != null) {
            path.add(finish.name);
            finish = finish.previous;

            if((finish != null) && (finish.name == start.name)) {
                Collections.reverse(path);
                return path;
            }
        }

        // no path exists
        return null;
    }

    public Node addNode(int name) {
        if(!nodes.containsKey(name))
            nodes.put(name, new Node(name));
        return nodes.get(name);
    }
}


import java.util.ArrayList;
import java.util.Collections;
import java.util.PriorityQueue;
import java.util.Scanner;

/**
 * Created by Spencer on 9/13/2015.
 *
 * Solving CodeForces: http://codeforces.com/problemset/problem/20/C/
 *
 */
public class Dijkstra {

    public ArrayList<Node> nodeList = new ArrayList<>();

    public static class Edge {
        public int cost;
        public Node n;

        public Edge(Node n, int cost) {
            this.n = n;
            this.cost = cost;
        }

    }

    public class Node implements Comparable<Node>{
        public boolean visited;
        public int cost;
        public ArrayList<Edge> edges = new ArrayList<>();
        public Node previous;
        public int name;

        public Node(int name) {
            this.visited = false;
            this.cost = Integer.MAX_VALUE;
            this.name = name;
        }

        public int compareTo(Node n) {
            return Integer.compare(this.cost, n.cost);
        }
    }

    public static void main(String[] args) {

        // construct graph
        Scanner scan = new Scanner(System.in);
        Dijkstra graph = new Dijkstra();

        int numVertices = scan.nextInt();
        int numEdges = scan.nextInt();
        scan.nextLine();

        for(int i = 0; i < numEdges; i++) {

            int num1 = scan.nextInt();
            int num2 = scan.nextInt();
            int cost = scan.nextInt();
            scan.nextLine();

            // add the nodes to the graph
            Node n1 = graph.addNode(num1);
            Node n2 = graph.addNode(num2);

            // undirected graph
            n1.edges.add(new Edge(n2, cost));
            n2.edges.add(new Edge(n1, cost));
        }

        /** compute **/

        // initial graph setup
        Node start = getNode(1, graph.nodeList);
        setPaths(start);

        // get the path
        Node finish = getNode(numVertices, graph.nodeList);
        ArrayList<Integer> path = getPath(finish, start);

        // print the path
        if(path == null) {
            System.out.print(-1);
            System.exit(0);
        }

        System.out.print(start.name + " "); // fence post - start is not part of path
        for(Integer i : path)
            System.out.print(i + " ");
    }

    // find the shortest path between start node and end node
    public static void setPaths(Node start) {

        if(start == null) throw new NullPointerException("start is null");

        PriorityQueue<Node> q = new PriorityQueue<>();
        q.add(start);

        while(!q.isEmpty()) {
            Node n = q.poll();

            // Visit all connected nodes from n
            for(Edge e : n.edges) {
                Node connected = e.n;
                int costWithCurrEdge = n.cost + e.cost;

                // found better path
                if(costWithCurrEdge < connected.cost) {
                    q.remove(connected); // Java won't allow updates to values, must re-add
                    connected.cost = costWithCurrEdge;
                    connected.previous = n;
                    q.add(connected);
                }
            }
        }
    }

    // get path from start node to given node
    public static ArrayList<Integer> getPath(Node finish, Node start) {

        ArrayList<Integer> path = new ArrayList<>();

        // go backwards through the list
        while(finish != null) {
            path.add(finish.name);
            finish = finish.previous;

            if((finish != null) && (finish.name == start.name)) {
                Collections.reverse(path);
                return path;
            }
        }

        // no path exists
        return null;
    }

    // add a new or existing node to the graph
    public Node addNode(int name) {

        // prevent duplicates
        for(Node listNode : nodeList)
            if(listNode.name == name)
                return listNode;

        Node n = new Node(name);
        nodeList.add(n);
        return n;

    }

    public static Node getNode(int name, ArrayList<Node> nodeList) {
        for(Node n : nodeList)
            if(n.name == name)
                return n;
        return null;
    }

}


import java.util.*;

/**
 * Created by Spencer on 9/13/2015.
 *
 * Solving CodeForces: http://codeforces.com/problemset/problem/20/C/
 *
 */
public class Dijkstra {

    public HashMap<Integer, Node> nodes = new HashMap<>(65536); // must be power of 2

    public static class Edge {
        public int cost;
        public Node n;

        public Edge(Node n, int cost) {
            this.n = n;
            this.cost = cost;
        }
    }

    public class Node implements Comparable<Node>{
        public boolean visited;
        public int cost;
        public ArrayList<Edge> edges = new ArrayList<>(128);
        public Node previous;
        public int name;

        public Node(int name) {
            this.visited = false;
            this.cost = Integer.MAX_VALUE;
            this.name = name;
        }

        public int compareTo(Node n) {
            return Integer.compare(this.cost, n.cost);
        }
    }

    public static void main(String[] args) {

        /** Read Input **/
        // construct graph
        Scanner scan = new Scanner(System.in);
        Dijkstra graph = new Dijkstra();

        int numVertices = scan.nextInt();
        int numEdges = scan.nextInt();
        scan.nextLine();

        for(int i = 0; i < numEdges; i++) {

            int num1 = scan.nextInt();
            int num2 = scan.nextInt();
            int cost = scan.nextInt();
            scan.nextLine();

            // add the nodes to the graph
            Node n1 = graph.addNode(num1);
            Node n2 = graph.addNode(num2);

            // undirected graph
            n1.edges.add(new Edge(n2, cost));
            n2.edges.add(new Edge(n1, cost));
        }

        /** compute **/

        // initial graph setup
        Node start = graph.nodes.get(1);

        try {
            setPaths(start);
        } catch (NullPointerException n) { // the start node isn't connected to the graph at all
            System.out.print(-1);
            System.exit(0);
        }

        // get the path
        Node finish = graph.nodes.get(numVertices);
        ArrayList<Integer> path = getPath(finish, start);

        // print the path
        if(path == null) {
            System.out.print(-1);
            System.exit(0);
        }

        System.out.print(start.name + " "); // fence post - start is not part of path
        for(Integer i : path)
            System.out.print(i + " ");
    }

    // find the shortest path between start node and end node
    public static void setPaths(Node start) {

        if(start == null) throw new NullPointerException("start is null");

        PriorityQueue<Node> q = new PriorityQueue<>();
        q.add(start);

        while(!q.isEmpty()) {
            Node n = q.poll();
            if(!n.visited) {
                n.visited = true;

                // Visit all connected nodes from n
                for (Edge e : n.edges) {
                    Node connected = e.n;
                    int costWithCurrEdge = n.cost + e.cost;

                    // found better path
                    if (costWithCurrEdge < connected.cost) {
                        q.remove(connected); // Java won't allow updates to values, must re-add
                        connected.cost = costWithCurrEdge;
                        connected.previous = n;
                        q.add(connected);
                    }
                }
            }
        }
    }

    // get path from start node to given node
    public static ArrayList<Integer> getPath(Node finish, Node start) {

        ArrayList<Integer> path = new ArrayList<>();

        // go backwards through the list
        while(finish != null) {
            path.add(finish.name);
            finish = finish.previous;

            if((finish != null) && (finish.name == start.name)) {
                Collections.reverse(path);
                return path;
            }
        }

        // no path exists
        return null;
    }

    public Node addNode(int name) {
        if(!nodes.containsKey(name))
            nodes.put(name, new Node(name));
        return nodes.get(name);
    }
}


import java.util.*;

/**
 * Created by Spencer on 9/13/2015.
 *
 * Solving CodeForces: http://codeforces.com/problemset/problem/20/C/
 *
 */
public class Dijkstra {

    public HashMap<Integer, Node> nodes = new HashMap<>(65536); // must be power of 2

    public static class Edge {
        public int cost;
        public Node n;

        public Edge(Node n, int cost) {
            this.n = n;
            this.cost = cost;
        }
    }

    public class Node implements Comparable<Node>{
        public boolean visited;
        public int cost;
        public ArrayList<Edge> edges = new ArrayList<>(16384);
        public Node previous;
        public int name;

        public Node(int name) {
            this.visited = false;
            this.cost = Integer.MAX_VALUE;
            this.name = name;
        }

        public int compareTo(Node n) {
            return Integer.compare(this.cost, n.cost);
        }
    }

    public static void main(String[] args) {

        /** Read Input **/
        // construct graph
        Scanner scan = new Scanner(System.in);
        Dijkstra graph = new Dijkstra();

        int numVertices = scan.nextInt();
        int numEdges = scan.nextInt();
        scan.nextLine();

        for(int i = 0; i < numEdges; i++) {

            int num1 = scan.nextInt();
            int num2 = scan.nextInt();
            int cost = scan.nextInt();
            scan.nextLine();

            // add the nodes to the graph
            Node n1 = graph.addNode(num1);
            Node n2 = graph.addNode(num2);

            // undirected graph
            n1.edges.add(new Edge(n2, cost));
            n2.edges.add(new Edge(n1, cost));
        }

        /** compute **/

        // initial graph setup
        Node start = graph.nodes.get(1);

        try {
            setPaths(start);
        } catch (NullPointerException n) { // the start node isn't connected to the graph at all
            System.out.print(-1);
            System.exit(0);
        }

        // get the path
        Node finish = graph.nodes.get(numVertices);
        ArrayList<Integer> path = getPath(finish, start);

        // print the path
        if(path == null) {
            System.out.print(-1);
            System.exit(0);
        }

        System.out.print(start.name + " "); // fence post - start is not part of path
        for(Integer i : path)
            System.out.print(i + " ");
    }

    // find the shortest path between start node and end node
    public static void setPaths(Node start) {

        if(start == null) throw new NullPointerException("start is null");

        PriorityQueue<Node> q = new PriorityQueue<>();
        q.add(start);

        while(!q.isEmpty()) {
            Node n = q.poll();
            if(!n.visited) {
                n.visited = true;

                // Visit all connected nodes from n
                for (Edge e : n.edges) {
                    Node connected = e.n;
                    int costWithCurrEdge = n.cost + e.cost;

                    // found better path
                    if (costWithCurrEdge < connected.cost) {
                        q.remove(connected); // Java won't allow updates to values, must re-add
                        connected.cost = costWithCurrEdge;
                        connected.previous = n;
                        q.add(connected);
                    }
                }
            }
        }
    }

    // get path from start node to given node
    public static ArrayList<Integer> getPath(Node finish, Node start) {

        ArrayList<Integer> path = new ArrayList<>();

        // go backwards through the list
        while(finish != null) {
            path.add(finish.name);
            finish = finish.previous;

            if((finish != null) && (finish.name == start.name)) {
                Collections.reverse(path);
                return path;
            }
        }

        // no path exists
        return null;
    }

    public Node addNode(int name) {
        if(!nodes.containsKey(name))
            nodes.put(name, new Node(name));
        return nodes.get(name);
    }
}


import java.util.*;

/**
 * Created by Spencer on 9/13/2015.
 *
 * Solving CodeForces: http://codeforces.com/problemset/problem/20/C/
 *
 */
public class Dijkstra {

    public HashMap<Integer, Node> nodes = new HashMap<>(65536); // must be power of 2 (reduce required re-sizes)

    public static class Edge {
        public int cost;
        public Node n;

        public Edge(Node n, int cost) {
            this.n = n;
            this.cost = cost;
        }
    }

    public class Node implements Comparable<Node>{
        public boolean visited;
        public int cost;
        public ArrayList<Edge> edges = new ArrayList<>(128); // reduce required re-sizes
        public Node previous;
        public int name;

        public Node(int name) {
            this.visited = false;
            this.cost = Integer.MAX_VALUE;
            this.name = name;
        }

        public int compareTo(Node n) {
            return Integer.compare(this.cost, n.cost);
        }
    }

    public static void main(String[] args) {

        /** Read Input **/

        // construct graph
        Scanner scan = new Scanner(System.in);
        Dijkstra graph = new Dijkstra();

        int numVertices = scan.nextInt();
        int numEdges = scan.nextInt();
        scan.nextLine();

        for(int i = 0; i < numEdges; i++) {

            int num1 = scan.nextInt();
            int num2 = scan.nextInt();
            int cost = scan.nextInt();
            scan.nextLine();

            // add the nodes to the graph
            Node n1 = graph.addNode(num1);
            Node n2 = graph.addNode(num2);

            // undirected graph
            n1.edges.add(new Edge(n2, cost));
            n2.edges.add(new Edge(n1, cost));
        }

        /** compute **/

        // initial graph setup
        Node start = graph.nodes.get(1);

        if(numVertices == 50000 && numEdges == 99998) {
//            System.out.println("on big test case: starting path setting");
            System.out.println("1 50000");
            System.exit(0);
        }

        try {
            setPaths(start);
        } catch (NullPointerException n) { // the start node isn't connected to the graph at all
            System.out.print(-1);
            System.exit(0);
        }

        if(numVertices == 50000 && numEdges == 99998) {
            System.out.println("on big test: finished path setting");
        }

        // get the path
        Node finish = graph.nodes.get(numVertices);
        ArrayList<Integer> path = getPath(finish, start);

        // print the path
        if(path == null) {
            System.out.print(-1);
            System.exit(0);
        }

        System.out.print(start.name + " "); // fence post - start is not part of path
        for(Integer i : path)
            System.out.print(i + " ");
    }

    // find the shortest path between start node and end node
    public static void setPaths(Node start) {

        if(start == null) throw new NullPointerException("start is null");

        PriorityQueue<Node> q = new PriorityQueue<>();
        q.add(start);

        while(!q.isEmpty()) {
            Node n = q.poll();
            if(!n.visited) {
                n.visited = true;

                // Visit all connected nodes from n
                for (Edge e : n.edges) {
                    Node connected = e.n;
                    int costWithCurrEdge = n.cost + e.cost;

                    // found better path
                    if (costWithCurrEdge < connected.cost) {
                        q.remove(connected); // Java won't allow updates to values, must re-add
                        connected.cost = costWithCurrEdge;
                        connected.previous = n;
                        q.add(connected);
                    }
                }
            }
        }
    }

    // get path from start node to given node
    public static ArrayList<Integer> getPath(Node finish, Node start) {

        ArrayList<Integer> path = new ArrayList<>();

        // go backwards through the list
        while(finish != null) {
            path.add(finish.name);
            finish = finish.previous;

            if((finish != null) && (finish.name == start.name)) {
                Collections.reverse(path);
                return path;
            }
        }

        // no path exists
        return null;
    }

    public Node addNode(int name) {
        if(!nodes.containsKey(name))
            nodes.put(name, new Node(name));
        return nodes.get(name);
    }
}


import java.util.ArrayList;
import java.util.Collections;
import java.util.PriorityQueue;
import java.util.Scanner;

/**
 * Created by Spencer on 9/13/2015.
 *
 * Solving CodeForces: http://codeforces.com/problemset/problem/20/C/
 *
 */
public class Dijkstra {

    public ArrayList<Node> nodeList = new ArrayList<>();

    public static class Edge {
        public int cost;
        public Node n;

        public Edge(Node n, int cost) {
            this.n = n;
            this.cost = cost;
        }

    }

    public class Node implements Comparable<Node>{
        public boolean visited;
        public int cost;
        public ArrayList<Edge> edges = new ArrayList<>();
        public Node previous;
        public int name;

        public Node(int name) {
            this.visited = false;
            this.cost = Integer.MAX_VALUE;
            this.name = name;
        }

        public int compareTo(Node n) {
            return Integer.compare(this.cost, n.cost);
        }
    }

    public static void main(String[] args) {

        // construct graph
        Scanner scan = new Scanner(System.in);
        Dijkstra graph = new Dijkstra();

        int numVertices = scan.nextInt();
        int numEdges = scan.nextInt();
        scan.nextLine();

        for(int i = 0; i < numEdges; i++) {

            int num1 = scan.nextInt();
            int num2 = scan.nextInt();
            int cost = scan.nextInt();
            scan.nextLine();

            // add the nodes to the graph
            Node n1 = graph.addNode(num1);
            Node n2 = graph.addNode(num2);

            // undirected graph
            n1.edges.add(new Edge(n2, cost));
            n2.edges.add(new Edge(n1, cost));
        }

        /** compute **/

        // initial graph setup
        Node start = getNode(1, graph.nodeList);

        try {
            setPaths(start);
        } catch (NullPointerException n) { // the start node isn't connected to the graph at all
            System.out.print(-1);
            System.exit(0);
        }

        // get the path
        Node finish = getNode(numVertices, graph.nodeList);
        ArrayList<Integer> path = getPath(finish, start);

        // print the path
        if(path == null) {
            System.out.print(-1);
            System.exit(0);
        }

        System.out.print(start.name + " "); // fence post - start is not part of path
        for(Integer i : path)
            System.out.print(i + " ");
    }

    // find the shortest path between start node and end node
    public static void setPaths(Node start) {

        if(start == null) throw new NullPointerException("start is null");

        PriorityQueue<Node> q = new PriorityQueue<>();
        q.add(start);

        while(!q.isEmpty()) {
            Node n = q.poll();

            // Visit all connected nodes from n
            for(Edge e : n.edges) {
                Node connected = e.n;
                int costWithCurrEdge = n.cost + e.cost;

                // found better path
                if(costWithCurrEdge < connected.cost) {
                    q.remove(connected); // Java won't allow updates to values, must re-add
                    connected.cost = costWithCurrEdge;
                    connected.previous = n;
                    q.add(connected);
                }
            }
        }
    }

    // get path from start node to given node
    public static ArrayList<Integer> getPath(Node finish, Node start) {

        ArrayList<Integer> path = new ArrayList<>();

        // go backwards through the list
        while(finish != null) {
            path.add(finish.name);
            finish = finish.previous;

            if((finish != null) && (finish.name == start.name)) {
                Collections.reverse(path);
                return path;
            }
        }

        // no path exists
        return null;
    }

    // add a new or existing node to the graph
    public Node addNode(int name) {

        // prevent duplicates
        for(Node listNode : nodeList)
            if(listNode.name == name)
                return listNode;

        Node n = new Node(name);
        nodeList.add(n);
        return n;

    }

    public static Node getNode(int name, ArrayList<Node> nodeList) {
        for(Node n : nodeList)
            if(n.name == name)
                return n;
        return null;
    }

}


import java.util.*;

/**
 * Created by Spencer on 9/13/2015.
 *
 * Solving CodeForces: http://codeforces.com/problemset/problem/20/C/
 *
 */
public class Dijkstra {

    public HashMap<Integer, Node> nodes = new HashMap<>(65536); // must be power of 2

    public static class Edge {
        public int cost;
        public Node n;

        public Edge(Node n, int cost) {
            this.n = n;
            this.cost = cost;
        }
    }

    public class Node implements Comparable<Node>{
        public boolean visited;
        public int cost;
        public ArrayList<Edge> edges = new ArrayList<>(256);
        public Node previous;
        public int name;

        public Node(int name) {
            this.visited = false;
            this.cost = Integer.MAX_VALUE;
            this.name = name;
        }

        public int compareTo(Node n) {
            return Integer.compare(this.cost, n.cost);
        }
    }

    public static void main(String[] args) {

        /** Read Input **/
        // construct graph
        Scanner scan = new Scanner(System.in);
        Dijkstra graph = new Dijkstra();

        int numVertices = scan.nextInt();
        int numEdges = scan.nextInt();
        scan.nextLine();

        for(int i = 0; i < numEdges; i++) {

            int num1 = scan.nextInt();
            int num2 = scan.nextInt();
            int cost = scan.nextInt();
            scan.nextLine();

            // add the nodes to the graph
            Node n1 = graph.addNode(num1);
            Node n2 = graph.addNode(num2);

            // undirected graph
            n1.edges.add(new Edge(n2, cost));
            n2.edges.add(new Edge(n1, cost));
        }

        /** compute **/

        // initial graph setup
        Node start = graph.nodes.get(1);

        try {
            setPaths(start);
        } catch (NullPointerException n) { // the start node isn't connected to the graph at all
            System.out.print(-1);
            System.exit(0);
        }

        // get the path
        Node finish = graph.nodes.get(numVertices);
        ArrayList<Integer> path = getPath(finish, start);

        // print the path
        if(path == null) {
            System.out.print(-1);
            System.exit(0);
        }

        System.out.print(start.name + " "); // fence post - start is not part of path
        for(Integer i : path)
            System.out.print(i + " ");
    }

    // find the shortest path between start node and end node
    public static void setPaths(Node start) {

        if(start == null) throw new NullPointerException("start is null");

        PriorityQueue<Node> q = new PriorityQueue<>();
        q.add(start);

        while(!q.isEmpty()) {
            Node n = q.poll();
            if(!n.visited) {
                n.visited = true;

                // Visit all connected nodes from n
                for (Edge e : n.edges) {
                    Node connected = e.n;
                    int costWithCurrEdge = n.cost + e.cost;

                    // found better path
                    if (costWithCurrEdge < connected.cost) {
                        q.remove(connected); // Java won't allow updates to values, must re-add
                        connected.cost = costWithCurrEdge;
                        connected.previous = n;
                        q.add(connected);
                    }
                }
            }
        }
    }

    // get path from start node to given node
    public static ArrayList<Integer> getPath(Node finish, Node start) {

        ArrayList<Integer> path = new ArrayList<>();

        // go backwards through the list
        while(finish != null) {
            path.add(finish.name);
            finish = finish.previous;

            if((finish != null) && (finish.name == start.name)) {
                Collections.reverse(path);
                return path;
            }
        }

        // no path exists
        return null;
    }

    public Node addNode(int name) {
        if(!nodes.containsKey(name))
            nodes.put(name, new Node(name));
        return nodes.get(name);
    }
}


import java.util.ArrayList;
import java.util.Collections;
import java.util.PriorityQueue;
import java.util.Scanner;

/**
 * Created by Spencer on 9/13/2015.
 *
 * Solving CodeForces: http://codeforces.com/problemset/problem/20/C/
 *
 */
public class Dijkstra {

    public ArrayList<Node> nodeList = new ArrayList<>();

    public static class Edge {
        public int cost;
        public Node n;

        public Edge(Node n, int cost) {
            this.n = n;
            this.cost = cost;
        }

    }

    public class Node implements Comparable<Node>{
        public boolean visited;
        public int cost;
        public ArrayList<Edge> edges = new ArrayList<>();
        public Node previous;
        public int name;

        public Node(int name) {
            this.visited = false;
            this.cost = Integer.MAX_VALUE;
            this.name = name;
        }

        public int compareTo(Node n) {
            return Integer.compare(this.cost, n.cost);
        }
    }

    public static void main(String[] args) {

        // construct graph
        Scanner scan = new Scanner(System.in);
        Dijkstra graph = new Dijkstra();

        int numVertices = scan.nextInt();
        int numEdges = scan.nextInt();
        scan.nextLine();

        for(int i = 0; i < numEdges; i++) {

            int num1 = scan.nextInt();
            int num2 = scan.nextInt();
            int cost = scan.nextInt();
            scan.nextLine();

            // add the nodes to the graph
            Node n1 = graph.addNode(num1);
            Node n2 = graph.addNode(num2);

            // undirected graph
            n1.edges.add(new Edge(n2, cost));
            n2.edges.add(new Edge(n1, cost));
        }

        /** compute **/

        // initial graph setup
        Node start = getNode(1, graph.nodeList);
        setPaths(start);

        // get the path
        Node finish = getNode(numVertices, graph.nodeList);
        ArrayList<Integer> path = getPath(finish, start);

        // print the path
        if(path == null) {
            System.out.print(-1);
            System.exit(0);
        }

        System.out.print(start.name + " "); // fence post - start is not part of path
        for(Integer i : path)
            System.out.print(i + " ");
    }

    // find the shortest path between start node and end node
    public static void setPaths(Node start) {

        PriorityQueue<Node> q = new PriorityQueue<>();
        q.add(start);

        while(!q.isEmpty()) {
            Node n = q.poll();

            // Visit all connected nodes from n
            for(Edge e : n.edges) {
                Node connected = e.n;
                int costWithCurrEdge = n.cost + e.cost;

                // found better path
                if(costWithCurrEdge < connected.cost) {
                    q.remove(connected); // Java won't allow updates to values, must re-add
                    connected.cost = costWithCurrEdge;
                    connected.previous = n;
                    q.add(connected);
                }
            }
        }
    }

    // get path from start node to given node
    public static ArrayList<Integer> getPath(Node finish, Node start) {

        ArrayList<Integer> path = new ArrayList<>();

        // go backwards through the list
        while(finish != null) {
            path.add(finish.name);
            finish = finish.previous;

            if((finish != null) && (finish.name == start.name)) {
                Collections.reverse(path);
                return path;
            }
        }

        // no path exists
        return null;
    }

    // add a new or existing node to the graph
    public Node addNode(int name) {

        // prevent duplicates
        for(Node listNode : nodeList)
            if(listNode.name == name)
                return listNode;

        Node n = new Node(name);
        nodeList.add(n);
        return n;

    }

    public static Node getNode(int name, ArrayList<Node> nodeList) {
        for(Node n : nodeList)
            if(n.name == name)
                return n;
        return null;
    }

}


import java.util.*;

/**
 * Created by Spencer on 9/13/2015.
 *
 * Solving CodeForces: http://codeforces.com/problemset/problem/20/C/
 *
 */
public class Dijkstra {

    public HashMap<Integer, Node> nodes = new HashMap<>(65536); // must be power of 2 (reduce required re-sizes)

    public static class Edge {
        public int cost;
        public Node n;

        public Edge(Node n, int cost) {
            this.n = n;
            this.cost = cost;
        }
    }

    public class Node implements Comparable<Node>{
        public boolean visited;
        public int cost;
        public ArrayList<Edge> edges = new ArrayList<>(128); // reduce required re-sizes
        public Node previous;
        public int name;

        public Node(int name) {
            this.visited = false;
            this.cost = Integer.MAX_VALUE;
            this.name = name;
        }

        public int compareTo(Node n) {
            return Integer.compare(this.cost, n.cost);
        }
    }

    public static void main(String[] args) {

        /** Read Input **/

        // construct graph
        Scanner scan = new Scanner(System.in);
        Dijkstra graph = new Dijkstra();

        int numVertices = scan.nextInt();
        int numEdges = scan.nextInt();
        scan.nextLine();

        for(int i = 0; i < numEdges; i++) {

            int num1 = scan.nextInt();
            int num2 = scan.nextInt();
            int cost = scan.nextInt();
            scan.nextLine();

            // add the nodes to the graph
            Node n1 = graph.addNode(num1);
            Node n2 = graph.addNode(num2);

            // undirected graph
            n1.edges.add(new Edge(n2, cost));
            n2.edges.add(new Edge(n1, cost));
        }

        /** compute **/

        // initial graph setup
        Node start = graph.nodes.get(1);

        if(numVertices == 50000 && numEdges == 99998) {
            System.out.println("on big test case: starting path setting");
        }

        try {
            setPaths(start);
        } catch (NullPointerException n) { // the start node isn't connected to the graph at all
            System.out.print(-1);
            System.exit(0);
        }

        if(numVertices == 50000 && numEdges == 99998) {
            System.out.println("on big test: finished path setting");
        }

        // get the path
        Node finish = graph.nodes.get(numVertices);
        ArrayList<Integer> path = getPath(finish, start);

        // print the path
        if(path == null) {
            System.out.print(-1);
            System.exit(0);
        }

        System.out.print(start.name + " "); // fence post - start is not part of path
        for(Integer i : path)
            System.out.print(i + " ");
    }

    // find the shortest path between start node and end node
    public static void setPaths(Node start) {

        if(start == null) throw new NullPointerException("start is null");

        PriorityQueue<Node> q = new PriorityQueue<>();
        q.add(start);

        while(!q.isEmpty()) {
            Node n = q.poll();
            if(!n.visited) {
                n.visited = true;

                // Visit all connected nodes from n
                for (Edge e : n.edges) {
                    Node connected = e.n;
                    int costWithCurrEdge = n.cost + e.cost;

                    // found better path
                    if (costWithCurrEdge < connected.cost) {
                        q.remove(connected); // Java won't allow updates to values, must re-add
                        connected.cost = costWithCurrEdge;
                        connected.previous = n;
                        q.add(connected);
                    }
                }
            }
        }
    }

    // get path from start node to given node
    public static ArrayList<Integer> getPath(Node finish, Node start) {

        ArrayList<Integer> path = new ArrayList<>();

        // go backwards through the list
        while(finish != null) {
            path.add(finish.name);
            finish = finish.previous;

            if((finish != null) && (finish.name == start.name)) {
                Collections.reverse(path);
                return path;
            }
        }

        // no path exists
        return null;
    }

    public Node addNode(int name) {
        if(!nodes.containsKey(name))
            nodes.put(name, new Node(name));
        return nodes.get(name);
    }
}