def e_knapsack2(N, W, Goods):

    """

    Dと同じ設定だが、制約が違う(1 <= v_i <= 10^3 と価値の制約がゆるめ)

    """

    from collections import defaultdict



    # dp[v]: 価値vを達成するために要求される重さの最小値

    dp = defaultdict(lambda: float('inf'))

    dp[0] = 0

    # w, vの順序が逆になっているのはdpテーブルの都合上

    for w, v in Goods:

        for nv, nw in list(dp.items()):

            if nw + w <= W:

                dp[nv + v] = min(dp[nv + v], nw + w)

    # 遷移の仕方により、keyの値を達成する品物の重さの和がWを超えることは

    # ないので、keyの最大値を解とすればいい

    return max(dp.keys())



N, W = [int(i) for i in input().split()]

Goods = [[int(i) for i in input().split()] for j in range(N)]

print((e_knapsack2(N, W, Goods)))
def e_knapsack2(N, W, Goods):

    """

    Dと同じ設定だが、制約が違う(1 <= v_i <= 10^3 と価値の制約がゆるめ)

    """

    import numpy as np

    # dp[v]: 価値vを達成するのに必要な重量の最小値

    # dpの長さは、すべての荷物を入れたときの価値+1で十分

    # 各要素の初期値は、Wを超える値ならよい(np.infだとうまく動作しないが)

    max_value = np.sum(np.array(Goods), axis=0)[1]

    dp = np.full(max_value + 1, W + 1, dtype='int64')

    dp[0] = 0  # 価値0を達成する荷物の重量は0とする

    for w, v in Goods:

        # 価値i(0<=i<=max_value-v)のときの重さの最小値に対し

        # 注目している荷物を入れて、価値i+vのときの重さの最小値を更新

        np.minimum(dp[:-v] + w, dp[v:], out=dp[v:])

    return np.max(np.where(dp <= W))



N, W = [int(i) for i in input().split()]

Goods = [[int(i) for i in input().split()] for j in range(N)]

print((e_knapsack2(N, W, Goods)))
def e_knapsack2(N, W, Goods):
    """
    Dと同じ設定だが、制約が違う(1 <= v_i <= 10^3 と価値の制約がゆるめ)
    """
    from collections import defaultdict

    # dp[v]: 価値vを達成するために要求される重さの最小値
    dp = defaultdict(lambda: float("inf"))
    dp[0] = 0
    # w, vの順序が逆になっているのはdpテーブルの都合上
    for w, v in Goods:
        for nv, nw in list(dp.items()):
            if nw + w <= W:
                dp[nv + v] = min(dp[nv + v], nw + w)
    # 遷移の仕方により、keyの値を達成する品物の重さの和がWを超えることは
    # ないので、keyの最大値を解とすればいい
    return max(dp.keys())


N, W = [int(i) for i in input().split()]
Goods = [[int(i) for i in input().split()] for j in range(N)]
print((e_knapsack2(N, W, Goods)))

def e_knapsack2(N, W, Goods):
    """
    Dと同じ設定だが、制約が違う(1 <= v_i <= 10^3 と価値の制約がゆるめ)
    """
    import numpy as np

    # dp[v]: 価値vを達成するのに必要な重量の最小値
    # dpの長さは、すべての荷物を入れたときの価値+1で十分
    # 各要素の初期値は、Wを超える値ならよい(np.infだとうまく動作しないが)
    max_value = np.sum(np.array(Goods), axis=0)[1]
    dp = np.full(max_value + 1, W + 1, dtype="int64")
    dp[0] = 0  # 価値0を達成する荷物の重量は0とする
    for w, v in Goods:
        # 価値i(0<=i<=max_value-v)のときの重さの最小値に対し
        # 注目している荷物を入れて、価値i+vのときの重さの最小値を更新
        np.minimum(dp[:-v] + w, dp[v:], out=dp[v:])
    return np.max(np.where(dp <= W))


N, W = [int(i) for i in input().split()]
Goods = [[int(i) for i in input().split()] for j in range(N)]
print((e_knapsack2(N, W, Goods)))

-    from collections import defaultdict +    import numpy as np -    # dp[v]: 価値vを達成するために要求される重さの最小値 -    dp = defaultdict(lambda: float("inf")) -    dp[0] = 0 -    # w, vの順序が逆になっているのはdpテーブルの都合上 +    # dp[v]: 価値vを達成するのに必要な重量の最小値 +    # dpの長さは、すべての荷物を入れたときの価値+1で十分 +    # 各要素の初期値は、Wを超える値ならよい(np.infだとうまく動作しないが) +    max_value = np.sum(np.array(Goods), axis=0)[1] +    dp = np.full(max_value + 1, W + 1, dtype="int64") +    dp[0] = 0  # 価値0を達成する荷物の重量は0とする -        for nv, nw in list(dp.items()): -            if nw + w <= W: -                dp[nv + v] = min(dp[nv + v], nw + w) -    # 遷移の仕方により、keyの値を達成する品物の重さの和がWを超えることは -    # ないので、keyの最大値を解とすればいい -    return max(dp.keys()) +        # 価値i(0<=i<=max_value-v)のときの重さの最小値に対し +        # 注目している荷物を入れて、価値i+vのときの重さの最小値を更新 +        np.minimum(dp[:-v] + w, dp[v:], out=dp[v:]) +    return np.max(np.where(dp <= W))