# E - Knapsack 2

from collections import defaultdict





def knapsack_heavy(limit: int, weight: list, value: list) -> int:

    dp = defaultdict(lambda: 1 << 30)  # dp[i] := minimum weight at value i

    dp[0] = 0

    for w, v in zip(weight, value):

        for cur_v, cur_w in tuple(dp.items()):

            if w + cur_w <= limit:

                dp[v + cur_v] = min(dp[v + cur_v], w + cur_w)

    return max(dp.keys())





def main():

    N, W, *WV = list(map(int, open(0).read().split()))

    print((knapsack_heavy(W, WV[::2], WV[1::2])))





if __name__ == "__main__":

    main()

# E - Knapsack 2

def knapsack_heavy(weight_limit: int, weights: list, values: list) -> int:

    max_value = sum(values)

    dp = [0] + [1 << 30] * max_value  # dp[i] := minimum weight at value i

    for w, v in zip(weights, values):

        for cur_v in range(max_value, v - 1, -1):

            if dp[cur_v - v] + w < dp[cur_v]:

                dp[cur_v] = dp[cur_v - v] + w

    return max(v for v, w in enumerate(dp) if w <= weight_limit)





def main():

    N, W, *WV = list(map(int, open(0).read().split()))

    print((knapsack_heavy(W, WV[::2], WV[1::2])))





if __name__ == "__main__":

    main()

# E - Knapsack 2
from collections import defaultdict


def knapsack_heavy(limit: int, weight: list, value: list) -> int:
    dp = defaultdict(lambda: 1 << 30)  # dp[i] := minimum weight at value i
    dp[0] = 0
    for w, v in zip(weight, value):
        for cur_v, cur_w in tuple(dp.items()):
            if w + cur_w <= limit:
                dp[v + cur_v] = min(dp[v + cur_v], w + cur_w)
    return max(dp.keys())


def main():
    N, W, *WV = list(map(int, open(0).read().split()))
    print((knapsack_heavy(W, WV[::2], WV[1::2])))


if __name__ == "__main__":
    main()

# E - Knapsack 2
def knapsack_heavy(weight_limit: int, weights: list, values: list) -> int:
    max_value = sum(values)
    dp = [0] + [1 << 30] * max_value  # dp[i] := minimum weight at value i
    for w, v in zip(weights, values):
        for cur_v in range(max_value, v - 1, -1):
            if dp[cur_v - v] + w < dp[cur_v]:
                dp[cur_v] = dp[cur_v - v] + w
    return max(v for v, w in enumerate(dp) if w <= weight_limit)


def main():
    N, W, *WV = list(map(int, open(0).read().split()))
    print((knapsack_heavy(W, WV[::2], WV[1::2])))


if __name__ == "__main__":
    main()

-from collections import defaultdict - - -def knapsack_heavy(limit: int, weight: list, value: list) -> int: -    dp = defaultdict(lambda: 1 << 30)  # dp[i] := minimum weight at value i -    dp[0] = 0 -    for w, v in zip(weight, value): -        for cur_v, cur_w in tuple(dp.items()): -            if w + cur_w <= limit: -                dp[v + cur_v] = min(dp[v + cur_v], w + cur_w) -    return max(dp.keys()) +def knapsack_heavy(weight_limit: int, weights: list, values: list) -> int: +    max_value = sum(values) +    dp = [0] + [1 << 30] * max_value  # dp[i] := minimum weight at value i +    for w, v in zip(weights, values): +        for cur_v in range(max_value, v - 1, -1): +            if dp[cur_v - v] + w < dp[cur_v]: +                dp[cur_v] = dp[cur_v - v] + w +    return max(v for v, w in enumerate(dp) if w <= weight_limit)