// Original C++ solution (slower):
#define _GLIBCXX_DEBUG

typedef long long ll;

#include <bits/stdc++.h>



using namespace std;



ll mod = 1000000007;



template<class Type> inline bool chmax(Type& a, Type b) { if (a < b) { a = b; return 1; } return 0; }

template<class Type> inline bool chmin(Type& a, Type b) { if (a > b) { a = b; return 1; } return 0; }



template<class Type>

Type modpow(Type a, Type n, Type mod)

{

	Type res = 1;

	while (0 < n)

	{

		if (n & 1)

		{

			res = res * a % mod;

		}

		a = a * a % mod;

		n >>= 1;

	}

	return res;

}



template<class Type>

Type gcd(Type x, Type y)

{

	Type r;

	if (x < y)

	{

		swap(x, y);

	}



	while (0 < y)

	{

		r = x % y;

		x = y;

		y = r;

	}

	return x;

}



template<class Type>

bool isPrime(Type x)

{

	if (x == 2) return true;

	if (x < 2 || x % 2 == 0) return false;



	for (Type i = 3; i <= sqrt(x); i += 2)

	{

		if (x % i == 0) return false;

	}

	return true;

}



template<class Type>

vector<bool> eratos(Type n)

{

	vector<bool> isPrime(n + 1, true);

	isPrime[0] = isPrime[1] = false;

	for (Type i = 2; i <= n; i++)

	{

		if (isPrime[i])

		{

			Type j = i + i;

			while (j <= n)

			{

				isPrime[j] = false;

				j = j + i;

			}

		}

	}

	return isPrime;

}



bool binarySearchJudge(vector<int> a, int index, int key)

{

	if (key <= a[index]) return true;

	else return false;

}



int binarySearch(vector<int> a, int key)

{

	int ng = -1;

	int ok = a.size();

	while (1 < abs(ng - ok))

	{

		int mid = (ng + ok) / 2;

		if (binarySearchJudge(a, mid, key)) ok = mid;

		else ng = mid;

	}

	return a[ok] == key;

}



int main()

{

	int n, w, v;

	cin >> n >> w;

	v = n * 1000;

	vector<ll> weight(n);

	vector<ll> value(n);

	for (int i = 0; i < n; i++)

	{

		cin >> weight[i] >> value[i];

	}



	vector<vector<ll>> dp(n, vector<ll>(v + 1, INT_MAX));

	dp[0][0] = 0;

	for (int i = 1; i <= v; i++)

	{

		if (i <= value[0])

		{

			dp[0][i] = weight[0];

		}

	}



	for (int i = 1; i < n; i++)

	{

		for (ll j = 0; j <= v; j++)

		{

			if (j < value[i])

			{

				dp[i][j] = dp[i - 1][j];

			}

			else

			{

				dp[i][j] = min(dp[i - 1][j], dp[i - 1][j - value[i]] + weight[i]);

			}

		}

	}



	ll ans = 0;

	for (ll i = 0; i <= v; i++)

	{

		if (dp[n - 1][i] <= w)

		{

			ans = max(ans, i);

		}

	}

	cout << ans << endl;

}

// Optimized solution to the same problem (faster):
#include <iostream>

#include <string>

#include <algorithm>

#include <vector>

#include <map>

#include <bitset>

#include <stack>

#include <queue>

#include <list>

#include <iomanip>

#include <numeric>



using namespace std;

typedef long long ll;

ll mod = 1000000007;

const int INF = 1001001001;



template<class Type>

Type modpow(Type a, Type n, Type mod)

{

	Type res = 1;

	while (0 < n) {

		if (n & 1) {

			res = res * a % mod;

		}

		a = a * a % mod;

		n >>= 1;

	}

	return res;

}



template<class Type>

Type gcd(Type x, Type y)

{

	Type r;

	if (x < y) swap(x, y);



	while (0 < y) {

		r = x % y;

		x = y;

		y = r;

	}

	return x;

}



template<class Type>

Type lcm(Type x, Type y)

{

	return x * y / gcd(x, y);

}



template<class Type>

bool is_prime(Type x)

{

	if (x == 2) return true;

	if (x < 2 || x % 2 == 0) return false;



	for (Type i = 3; i <= sqrt(x); i += 2) {

		if (x % i == 0) return false;

	}

	return true;

}



template<class Type>

vector<bool> eratos(Type n)

{

	vector<bool> isPrime(n + 1, true);

	isPrime[0] = isPrime[1] = false;

	for (Type i = 2; i <= n; i++) {

		if (isPrime[i]) {

			Type j = i + i;

			while (j <= n) {

				isPrime[j] = false;

				j = j + i;

			}

		}

	}

	return isPrime;

}



bool binary_search_judge(vector<int> a, int index, int key)

{

	if (key <= a[index]) return true;

	else return false;

}



int binary_search(vector<int> a, int key)

{

	int ng = -1;

	int ok = a.size();

	while (1 < abs(ng - ok)) {

		int mid = (ng + ok) / 2;

		if (binary_search_judge(a, mid, key)) ok = mid;

		else ng = mid;

	}

	return a[ok] == key;

}



int main()

{

	int n, w;

	cin >> n >> w;

	vector<int> weight(n), value(n);

	for (int i = 0; i < n; i++) cin >> weight[i] >> value[i];

	int v_max = *max_element(value.begin(), value.end());



	vector<vector<int>> dp(n, vector<int>(n * v_max + 1, INF));

	dp[0][0] = 0;

	for (int j = 1; j <= value[0]; j++) dp[0][j] = weight[0];



	for (int i = 1; i < n; i++) {

		for (int j = 0; j <= n * v_max; j++) {

			dp[i][j] = dp[i - 1][j];

			if (0 <= j - value[i]) dp[i][j] = min(dp[i][j], dp[i - 1][j - value[i]] + weight[i]);

		}

	}



	int ans = 0;

	for (int j = 0; j <= n * v_max; j++) {

		if (dp[n - 1][j] <= w) ans = j;

	}

	cout << ans << endl;

}

// Fastest known solution for this problem: