CodeEff/ECCO huggingface dataset:
# Original solution
# E - Knapsack 2
from collections import defaultdict


def main():
    INF = 1 << 30
    N, W, *WV = list(map(int, open(0).read().split()))
    dp = defaultdict(lambda: INF)  # dp[i] := minimum weight at value i
    dp[0] = 0
    for w, v in zip(*[iter(WV)] * 2):
        for cur_v, cur_w in tuple(dp.items()):
            if w + cur_w <= W:
                dp[v + cur_v] = min(dp[v + cur_v], w + cur_w)
    print((max(dp.keys())))


if __name__ == "__main__":
    main()


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


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()
# Original solution
# 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()


# Optimized solution
# 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()
# Original solution
#!/usr/bin/env python3
from collections import deque, Counter
from heapq import heappop, heappush
from bisect import bisect_right

def main():
    N, W = list(map(int, input().split()))
    V = N * 10**3
    INF = 10**12
    dp = [INF] * (V+1)# dp[i]: 価値の総和をiにするための重さの最小値
    dp[0] = 0

    for _ in range(N):
        w, v = list(map(int, input().split()))
        for j in range(V,-1,-1):
            if j-v >= 0:
                dp[j] = min(dp[j],dp[j-v]+w)
    # print(dp)
    ans = -1
    for i in range(V+1):
        if dp[i] <= W:
            ans = i
    print(ans)

if __name__ == "__main__":
    main()


# Optimized solution
#!/usr/bin/env python3

def main():
    N, W = list(map(int, input().split()))
    V = N * 10**3
    INF = 10**12
    dp = [INF] * (V+1)# dp[i]: 価値の総和をiにするための重さの最小値
    dp[0] = 0

    for _ in range(N):
        w, v = list(map(int, input().split()))
        for j in range(V,-1,-1):
            if j-v >= 0:
                dp[j] = min(dp[j],dp[j-v]+w)
    # print(dp)
    ans = -1
    for i in range(V+1):
        if dp[i] <= W:
            ans = i
    print(ans)

if __name__ == "__main__":
    main()
# Original solution
n,w=list(map(int,input().split()))
l=[list(map(int,input().split())) for i in range(n)]

lim=n*10**3+1
dp=[[float('inf') for i in range(lim)] for i in range(n+1)]

for i in range(n+1):
 dp[i][0]=0

for i in range(n):
 for sum_v in range(lim):

  if sum_v-l[i][1]>=0:
   dp[i+1][sum_v] = min(dp[i+1][sum_v],dp[i][sum_v-l[i][1]]+l[i][0])

  dp[i+1][sum_v]=min(dp[i+1][sum_v],dp[i][sum_v])

ans=0
for i in range(lim):
 if dp[-1][i]<=w:
  ans=max(ans,i)
print(ans)

# Optimized solution
n,w=list(map(int,input().split()))
l=[list(map(int,input().split())) for i in range(n)]

lim=n*10**3+1
#dp=[[float('inf') for i in range(lim)] for i in range(n+1)]
dp=[[10**15 for i in range(lim)] for i in range(n+1)]

'''
for i in range(n+1):
 dp[i][0]=0
'''
dp[0][0]=0

for i in range(n):
 for sum_v in range(lim):

  if sum_v-l[i][1]>=0:
   dp[i+1][sum_v] = min(dp[i+1][sum_v],dp[i][sum_v-l[i][1]]+l[i][0])

  dp[i+1][sum_v]=min(dp[i+1][sum_v],dp[i][sum_v])

ans=0
for i in range(lim):
 if dp[-1][i]<=w:
  ans=max(ans,i)
print(ans)
# Original solution
n,w=list(map(int,input().split()))
l=[list(map(int,input().split())) for i in range(n)]

lim=n*10**3+1
#dp=[[float('inf') for i in range(lim)] for i in range(n+1)]
dp=[[10**15 for i in range(lim)] for i in range(n+1)]

'''
for i in range(n+1):
 dp[i][0]=0
'''
dp[0][0]=0

for i in range(n):
 for sum_v in range(lim):

  if sum_v-l[i][1]>=0:
   dp[i+1][sum_v] = min(dp[i+1][sum_v],dp[i][sum_v-l[i][1]]+l[i][0])

  dp[i+1][sum_v]=min(dp[i+1][sum_v],dp[i][sum_v])

ans=0
for i in range(lim):
 if dp[-1][i]<=w:
  ans=max(ans,i)
print(ans)

# Optimized solution
n,w=list(map(int,input().split()))
l=[list(map(int,input().split())) for i in range(n)]

lim=n*10**3+1
#dp=[[float('inf') for i in range(lim)] for i in range(n+1)]
dp=[[10**15 for i in range(lim)] for i in range(n+1)]

for i in range(n+1):
 dp[i][0]=0

#dp[0][0]=0

for i in range(n):
 for sum_v in range(lim):

  if sum_v-l[i][1]>=0:
   dp[i+1][sum_v] = min(dp[i+1][sum_v],dp[i][sum_v-l[i][1]]+l[i][0])

  dp[i+1][sum_v]=min(dp[i+1][sum_v],dp[i][sum_v])

ans=0
for i in range(lim):
 if dp[-1][i]<=w:
  ans=max(ans,i)
print(ans)
# Original solution
import sys

input = sys.stdin.readline


def main():
    N, W = [int(x) for x in input().split()]
    WV = [[int(x) for x in input().split()] for _ in range(N)]

    sumv = 0
    for w, v in WV:
        sumv += v

    dp = [[float("inf")] * (sumv + 1) for j in range(N + 1)]

    for i in range(1, N + 1):
        for j in range(sumv + 1):
            w, v = WV[i - 1]
            if j <= v:
                dp[i][j] = min(w, dp[i - 1][j])
            else:
                dp[i][j] = min(dp[i - 1][j], w + dp[i - 1][j - v])

    ans = 0
    for i in range(sumv + 1):
        if dp[N][i] > W:
            break
        else:
            ans = i

    print(ans)


if __name__ == '__main__':
    main()


# Optimized solution
import sys

input = sys.stdin.readline


def main():
    N, W = [int(x) for x in input().split()]
    WV = [[int(x) for x in input().split()] for _ in range(N)]

    sumv = 0
    for w, v in WV:
        sumv += v

    dp = [[10 ** 9 + 1] * (sumv + 1) for j in range(N + 1)]

    for i in range(1, N + 1):
        for j in range(sumv + 1):
            w, v = WV[i - 1]
            if j <= v:
                dp[i][j] = min(w, dp[i - 1][j])
            else:
                dp[i][j] = min(dp[i - 1][j], w + dp[i - 1][j - v])

    ans = 0
    for i in range(sumv + 1):
        if dp[N][i] > W:
            break
        else:
            ans = i

    print(ans)


if __name__ == '__main__':
    main()
# Original solution
import sys

# input処理を高速化する
input = sys.stdin.readline

# 入力
N, W = list(map(int, input().split()))
# sum_vの取りうる上限値
MAX_V = (10**3+1) * N

# 最小値を求めるので無限大の値
f_inf = float('inf')

def chmin(a, b):
    if a <= b:
        return a
    else:
        return b

def knapsack(n, w):
    # dpの初期化　dp[i][sum_v]は重さの総和の最小値
    dp = [[f_inf for i in range(MAX_V)] for j in range(N+1)]
    # 初期条件
    dp[0][0] = 0
    # forは全て関数の中で回す。
    # 入力
    for i in range(N):
        w, v = list(map(int, input().split()))
        for sum_v in range(MAX_V):
            # i番目の品物を選ぶ場合
            if (sum_v -v >= 0):
                dp[i + 1][sum_v] = chmin(dp[i + 1][sum_v], dp[i][sum_v - v] + w)
            # i番目の品物を選ばない場合
            dp[i + 1][sum_v] = chmin(dp[i + 1][sum_v], dp[i][sum_v])
    #dp[N][sum_v]の値が、W以下であるsum_vの値の最大値
    ans = 0
    for sum_v in range(MAX_V):
        if dp[N][sum_v] <= W:
            ans = sum_v
    print(ans)

knapsack(N, W)




# Optimized solution
import sys

# input処理を高速化する
input = sys.stdin.readline

# 入力
N, W = list(map(int, input().split()))
# sum_vの取りうる上限値
MAX_V = (10**3) * N +1
# 最小値を求めるので無限大の値
f_inf = float('inf')

def knapsack(n, w):
    # dpの初期化　dp[sum_v]は重さの総和の最小値
    dp = [f_inf] * MAX_V
    # 初期条件
    dp[0] = 0
    sum_v = 0
    # forは全て関数の中で回す。
    # 入力
    for i in range(N):
        w, v = list(map(int, input().split()))
        for j in range(MAX_V, v-1, -1):
            new_weight = dp[j - v] + w
            if new_weight > W:
                continue
            if dp[j] > new_weight:
                dp[j] = new_weight

    ans = 0
    for sum_v in range(MAX_V):
        if dp[sum_v] <= W:
            ans = sum_v
    print(ans)

knapsack(N, W)
# Original solution
# -*- coding: utf-8 -*-
"""
Created on Tue Jan 21 18:19:39 2020

@author: matsui
"""


N,W=list(map(int,input().split()))
vi,wi=[],[]
for i in range(N):
    w,v=list(map(int,input().split()))
    wi.append(w)
    vi.append(v)
    

#L = sorted([list(map(int,input().split())) for i in range(N)])

M=int(sum(vi))
dp1=[sum(wi)+1]*(M+1)
#dp2=[sum(wi)+1]*(M+1)
dp1[0]=0
   
#L = sorted([list(map(int,input().split())) for i in range(N)])
s=0

for w, v in zip(wi,vi):
    s+=v
    for j in range(min(s,M),v-1,-1):
        if j >= v: 
            if dp1[j] > dp1[j-v]+w: dp1[j]=dp1[j-v]+w
        if dp1[j] > dp1[j]: dp1[j]=dp1[j]
    #print(dp1)
    #print(dp2)
    #dp1=[dp2[i] for i in range(M+1)]    
    
#print(max(dp))
m=0
for i in range(M+1):
    if dp1[i]<=W:
        m=i
print(m)
    


# Optimized solution
# -*- coding: utf-8 -*-
"""
Created on Tue Jan 21 18:19:39 2020

@author: matsui
"""


N,W=list(map(int,input().split()))
vi,wi=[],[]
for i in range(N):
    w,v=list(map(int,input().split()))
    wi.append(w)
    vi.append(v)
    

#L = sorted([list(map(int,input().split())) for i in range(N)])

M=int(sum(vi))
dp=[W+1]*(M+1)
dp[0]=0
   
#L = sorted([list(map(int,input().split())) for i in range(N)])
s=0

for w, v in zip(wi,vi):
    s+=v
    for j in range(min(s,M),v-1,-1):
        if dp[j] > dp[j-v]+w: dp[j]=dp[j-v]+w
    #print(dp)

m=0
for i in range(M+1):
    if dp[i]<=W:
        m=i
print(m)
# Original solution
N,W = list(map(int,input().split()))
c = [tuple(map(int,input().split())) for i in range(N)]
DP = [[float('inf') for i in range(10**3*N+1)] for i in range(N+1)]
DP[0][0] = 0
for i in range(N):
    for v in range(10**3*N+1):
        if v-c[i][1] < 0:
            DP[i+1][v] = DP[i][v]
        else:
            DP[i+1][v] = min(DP[i][v-c[i][1]]+c[i][0],DP[i][v])

ans = 0
DP = DP[N]
for v in range(10**3*N,-1,-1):
    if DP[v] <= W:
        ans = v
        break
print(ans)

# Optimized solution
INF = float('inf')
N,W = list(map(int,input().split()))
wv = [list(map(int,input().split())) for _ in range(N)]
V = 1000*N
dp = [[INF]*(V+1) for _ in range(N+1)]
dp[0][0]=0
for i in range(N):
    for j in range(V+1):
        if j-wv[i][1] >= 0:
            dp[i+1][j] = min(dp[i][j-wv[i][1]]+wv[i][0],dp[i][j])
        else:
            dp[i+1][j] = dp[i][j]

ans = 0
for i in range(N+1):
    for j in range(V+1):
        if dp[i][j] <= W:
            ans = max(ans,j)
print(ans)
# Original solution
import sys
input = sys.stdin.readline
def main():
    # input
    N,W = list(map(int,input().split()))
    w,v = [0]*N,[0]*N
    for i in range(N):
        w[i],v[i] = list(map(int,input().split()))
    
    # init dp
    v_max = sum(v)
    dp = [[float("inf") for i in range(v_max+1)] for _ in range(N)]
    dp[0][v[0]] = w[0]
    for i in range(N):
        dp[i][0] = 0

    for i in range(1,N):
        for j in range(v_max+1):
            if j<v[i]:
                dp[i][j] = dp[i-1][j]
            else:
                dp[i][j] = min(dp[i-1][j],dp[i-1][j-v[i]]+w[i])
    ans = 0
    for i in range(v_max+1):
        if dp[-1][i]==float("inf"):
            pass
        elif dp[-1][i]<=W:
            ans = i
    print(ans)
if __name__ == "__main__":
    main()

# Optimized solution
import sys
input = sys.stdin.readline
def main():
    # input
    N,W = list(map(int,input().split()))
    w,v = [0]*N,[0]*N
    for i in range(N):
        w[i],v[i] = list(map(int,input().split()))
    
    # init dp
    v_max = sum(v)
    dp = [[float("inf") for i in range(v_max+1)] for _ in range(N)]
    dp[0][v[0]] = w[0]
    for i in range(N):
        dp[i][0] = 0

    for i in range(1,N):
        for j in range(v_max+1):
            if j<v[i]:
                dp[i][j] = dp[i-1][j]
            else:
                dp[i][j] = min(dp[i-1][j],dp[i-1][j-v[i]]+w[i])
    ans = 0
    for i in range(v_max+1):
        if dp[-1][i]<=W:
            ans = i
        else:
            pass
    print(ans)
if __name__ == "__main__":
    main()
# Original solution
import sys
from _operator import itemgetter

stdin = sys.stdin

ni = lambda: int(ns())
na = lambda: list(map(int, stdin.readline().split()))
ns = lambda: stdin.readline().rstrip()

N, W = na()
maxV = 10 ** 5
dp = [[10**9+7] * (maxV+1) for i in range(N+1)]  # dp[i][v] i番目までで価値がvの時の重さの合計の最小値
dp[0][0] = 0
tp = [na() for i in range(N)]
list.sort(tp, key=itemgetter(0))
for i in range(1, N+1):
    wi, vi = tp[i - 1]
    for v in range(1, maxV+1):
        if v - vi >= 0:
            dp[i][v] = min(dp[i - 1][v], dp[i - 1][v - vi] + wi)
        else:
            dp[i][v] = dp[i - 1][v]
ans = -1
for i in range(1, N + 1):
    for v in range(1, maxV+1):
        if dp[i][v] <= W:
            ans = max(ans, v)
print(ans)

# Optimized solution
import sys

stdin = sys.stdin

ni = lambda: int(ns())
na = lambda: list(map(int, stdin.readline().split()))
ns = lambda: stdin.readline().rstrip()

N, W = na()
maxV = 10 ** 5
dp = [[10**9+7] * (maxV+1) for i in range(N+1)]  # dp[i][v] i番目までで価値がvの時の重さの合計の最小値
dp[0][0] = 0
tp = [na() for i in range(N)]
list.sort(tp, key=lambda x:x[0])
for i in range(1, N+1):
    wi, vi = tp[i - 1]
    for v in range(1, maxV+1):
        if v - vi >= 0:
            dp[i][v] = min(dp[i - 1][v], dp[i - 1][v - vi] + wi)
        else:
            dp[i][v] = dp[i - 1][v]
ans = -1
for i in range(1, N + 1):
    for v in range(1, maxV+1):
        if dp[i][v] <= W:
            ans = max(ans, v)
print(ans)
# Original solution
N,W=list(map(int,input().split()))
w=[]
v=[]
for _ in range(N):
    ww,vv=list(map(int,input().split()))
    w.append(ww)
    v.append(vv)
INF=float("inf")
max_v=10**5+1
dp=[[INF for i in range(max_v)] for j in range(N+1)]
dp[0][0]=0
for i in range(N):
    for j in range(max_v):
        if j - v[i]>=0:
            dp[i+1][j]=min(dp[i+1][j],dp[i][j-v[i]]+w[i])
        dp[i+1][j]=min(dp[i+1][j],dp[i][j])

for i in range(max_v):
    if dp[N][i] <=W:
        ans=i
print(ans)


# Optimized solution
N,W=list(map(int,input().split()))
w=[]
v=[]
for _ in range(N):
    ww,vv=list(map(int,input().split()))
    w.append(ww)
    v.append(vv)
INF=float("inf")
max_v=max(v)*N +1
dp=[[INF for i in range(max_v)] for j in range(N+1)]
dp[0][0]=0
for i in range(N):
    for j in range(max_v):
        if j - v[i]>=0:
            dp[i+1][j]=min(dp[i+1][j],dp[i][j-v[i]]+w[i])
        dp[i+1][j]=min(dp[i+1][j],dp[i][j])

for i in range(max_v):
    if dp[N][i] <=W:
        ans=i
print(ans)
# Original solution
n, m = list(map(int, input().split()))
inf = 10**11
dp = [inf] * (1000 * n + 1)
dp[0] = 0

for i in range(n):
    w, v = list(map(int, input().split()))
    for j in range(1000 * n - v, -1, -1):
        if dp[j] != inf:
            dp[j + v] = min(dp[j + v], dp[j] + w)
ans = 0
for a, b in enumerate(dp):
    if b <= m:
        ans = max(ans, a)
print(ans)


# Optimized solution
import sys
readline = sys.stdin.buffer.readline

def main():
    n, m = list(map(int, readline().split()))
    inf = 10**11
    dp = [inf] * (1000 * n + 1)
    dp[0] = 0

    for i in range(n):
        w, v = list(map(int, input().split()))
        for j in range(1000 * n - v, -1, -1):
            if dp[j] != inf:
                dp[j + v] = min(dp[j + v], dp[j] + w)
    ans = 0
    for a, b in enumerate(dp):
        if b <= m:
            ans = max(ans, a)
    print(ans)

if __name__ == "__main__":
    main()
# Original solution
def args():
    N, W = tuple(map(int, input().split()))

    Wi, Vi = [], []
    for _ in range(N):
        w, v = tuple(map(int, input().split()))
        Wi.append(w)
        Vi.append(v)

    # print(N, W)
    # print(Wi, Vi)

    return N, W, Wi, Vi


def solve(N, W, Wi, Vi):
    if N == 1:
        return Vi[0]

    x, y = N + 1, max(Vi) * N + 1
    DP = [[float("inf") for _ in range(y)] for _ in range(x)]

    # print(len(DP[0]))

    DP[0][0] = 0

    for i in range(N):
        value = Vi[i]
        w_max = max(Vi) * N
        for v in range(w_max):
            remain = v - value
            if 0 <= remain:
                # 選ぶ
                DP[i + 1][v] = min(DP[i + 1][v], DP[i][remain] + Wi[i])
            # 選ばない
            DP[i + 1][v] = min(DP[i + 1][v], DP[i][v])

    # print(DP)
    ans = 0
    for line in DP:
        for v, e in enumerate(line):
            if not e == float("inf") and e <= W:
                # print(v, e)
                ans = max(ans, v)

    # print(DP)

    return ans


if __name__ == '__main__':
    res = solve(*args())
    print(res)


# Optimized solution
def args():
    N, W = tuple(map(int, input().split()))

    Wi, Vi = [], []
    for _ in range(N):
        w, v = tuple(map(int, input().split()))
        Wi.append(w)
        Vi.append(v)

    # print(N, W)
    # print(Wi, Vi)

    return N, W, Wi, Vi


def solve(N, W, Wi, Vi):
    DP = [[float("inf")] * (sum(Vi) + 1) for _ in range(N + 1)]

    DP[0][0] = 0

    for i in range(N):
        value = Vi[i]
        w_max = sum(Vi) + 1
        for v in range(w_max):
            remain = v - value
            if 0 <= remain:
                # 選ぶ
                DP[i + 1][v] = min(DP[i + 1][v], DP[i][remain] + Wi[i])
            # 選ばない
            DP[i + 1][v] = min(DP[i + 1][v], DP[i][v])

    # print(DP)
    ans = 0
    for line in DP:
        for v, e in enumerate(line):
            if not e == float("inf") and e <= W:
                # print(v, e)
                ans = max(ans, v)

    # print(DP)

    return ans


if __name__ == '__main__':
    res = solve(*args())
    print(res)
# Original solution
#!/usr/bin/env python3
#dp5 #Knapsack 2
#個数制限ありナップサック
#1≤W≤10**9

def e():
    n,W = list(map(int,input().split()))
    wv = [list(map(int,input().split())) for _ in range(n)]
    #横:価値　縦:品物
    dp = [[float("inf") for _ in range(10**5+1)] for _ in range(n+1)]
    dp[0][0] = 0
    for i in range(1,n+1):
        for j in range(10**5+1):
            #i番目の品物の価値より価値の制限が小さいとき(i番目の品物が使えないとき)
            if j < wv[i-1][1]:
                #i-1番目の品物の重さと同じ
                dp[i][j] = dp[i-1][j]
            else:
                #i番目の品物を使い、重さを追加する場合と使わない場合の重さを比較
                dp[i][j] = min(dp[i-1][j],dp[i-1][j - wv[i-1][1]] + wv[i-1][0])
    ans = 0
    #重さWまでの価値最大値
    for i in range(10**5+1):
        if dp[n][i] <= W:
            ans = i
    print(ans)
if __name__ == '__main__':
    e()


# Optimized solution
#!/usr/bin/env python3
#dp5 #Knapsack 2
#個数制限ありナップサック
#1≤W≤10**9
import sys
def LI(): return list(map(int, sys.stdin.readline().split()))
def LIR(n): return [LI() for _ in range(n)]
def e():
    n,W = LI()
    wv = LIR(n)

    #横:価値　縦:品物
    dp = [[float("inf") for _ in range(10**5+1)] for _ in range(n+1)]
    dp[0][0] = 0
    for i in range(1,n+1):
        for j in range(10**5+1):
            #i番目の品物の価値より価値の制限が小さいとき(i番目の品物が使えないとき)
            if j < wv[i-1][1]:
                #i-1番目の品物の重さと同じ
                dp[i][j] = dp[i-1][j]
            else:
                #i番目の品物を使い、重さを追加する場合と使わない場合の重さを比較
                dp[i][j] = min(dp[i-1][j],dp[i-1][j - wv[i-1][1]] + wv[i-1][0])
    ans = 0
    #重さWまでの価値最大値
    for i in range(10**5+1):
        if dp[n][i] <= W:
            ans = i
    print(ans)
if __name__ == '__main__':
    e()
# Original solution
#!/usr/bin/env python3
#dp5 #Knapsack 2
#個数制限ありナップサック
#1≤W≤10**9
import sys
def LI(): return list(map(int, sys.stdin.readline().split()))
def LIR(n): return [LI() for _ in range(n)]
def e():
    n,W = LI()
    wv = LIR(n)

    #横:価値　縦:品物
    dp = [[float("inf") for _ in range(10**5+1)] for _ in range(n+1)]
    dp[0][0] = 0
    for i in range(1,n+1):
        for j in range(10**5+1):
            #i番目の品物の価値より価値の制限が小さいとき(i番目の品物が使えないとき)
            if j < wv[i-1][1]:
                #i-1番目の品物の重さと同じ
                dp[i][j] = dp[i-1][j]
            else:
                #i番目の品物を使い、重さを追加する場合と使わない場合の重さを比較
                dp[i][j] = min(dp[i-1][j],dp[i-1][j - wv[i-1][1]] + wv[i-1][0])
    ans = 0
    #重さWまでの価値最大値
    for i in range(10**5+1):
        if dp[n][i] <= W:
            ans = i
    print(ans)
if __name__ == '__main__':
    e()


# Optimized solution
#!/usr/bin/env python3
#EDPC E

import sys
import math
from bisect import bisect_right as br
from bisect import bisect_left as bl
sys.setrecursionlimit(1000000000)
from heapq import heappush, heappop,heappushpop
from collections import defaultdict
from itertools import accumulate
from collections import Counter
from collections import deque
from operator import itemgetter
from itertools import permutations
mod = 10**9 + 7
inf = float('inf')
def I(): return int(sys.stdin.readline())
def LI(): return list(map(int,sys.stdin.readline().split()))

n,W = LI()
wv = [LI() for _ in range(n)]
V = 0
for i in range(n):
    w,v = wv[i]
    V += v
    
dp = [[inf]*(V+1) for _ in range(n+1)]
dp[0][0] = 0
for i in range(n):
    w,v = wv[i]
    for j in range(V+1):
        if j < v:
            dp[i+1][j] = dp[i][j]
        else:
            dp[i+1][j] = min(dp[i][j],dp[i][j-v] + w)
res = 0
for i in range(V+1):
    if dp[-1][i] <= W:
        res = i
print(res)
# Original solution
n,w = list(map(int,input().split()))
w_ls, v_ls = [0] * n, [0] * n
for i in range(n):
    w_ls[i], v_ls[i] = list(map(int,input().split()))
V = sum(v_ls)
dp = [[float("inf")] * (V+1) for _ in range(n+1)]
dp[0][0] = 0
for i in range(n):
    for j in range(V+1):
        if j - v_ls[i] >= 0:
            dp[i+1][j] = min(dp[i+1][j], dp[i][j-v_ls[i]] + w_ls[i])
        dp[i+1][j] = min(dp[i+1][j], dp[i][j])

ans = 0
for j in range(V+1):
    if dp[n][j] <= w:
        ans = j

print(ans)

# Optimized solution
n,w_limit = list(map(int,input().split()))

item_ls = [[0,0]]
total_value = 0
for i in range(n):
    cost, value = list(map(int,input().split()))
    item_ls.append([cost, value])
    total_value += value


dp = [[float('inf')] * (total_value+1) for _ in range(n+1)]
dp[0][0] = 0
for i in range(1,n+1):
    item_cost, item_value = item_ls[i]
    for sum_value in range(0,total_value+1):
        if sum_value-item_value >= 0:
            dp[i][sum_value] = min(dp[i][sum_value], dp[i-1][sum_value-item_value] + item_cost)
        dp[i][sum_value] = min(dp[i][sum_value], dp[i-1][sum_value])

ans = 0
for value, cost in enumerate(dp[n]):
    if cost <= w_limit:
        ans = max(ans, value)
print(ans)
# Original solution
from pprint import pprint

n, w = list(map(int, input().split()))
wv = [list(map(int, input().split())) for _ in range(n)]

lim = 1
for i in range(n):
    lim += wv[i][1]

dp = [[float('inf')] * lim for _ in range(n+1)]
dp[0][0] = 0

for i in range(n):
    for j in range(lim):
        if j - wv[i][1] >= 0:
            dp[i+1][j] = min(dp[i][j - wv[i][1]] + wv[i][0], dp[i][j])
        else:
            dp[i+1][j] = min((dp[i][j], dp[i+1][j]))

ans = float('inf')

for i in reversed(list(range(lim))):
    if dp[-1][i] <= w:
        ans = min(i, ans)
        break
print(ans)

# Optimized solution
from pprint import pprint

n, w = list(map(int, input().split()))
wv = [list(map(int, input().split())) for _ in range(n)]

lim = 1
for i in range(n):
    lim += wv[i][1]

dp = [[float('inf')] * lim for _ in range(n+1)]
dp[0][0] = 0

for i in range(n):
    for j in range(lim):
        if j - wv[i][1] >= 0:
            dp[i+1][j] = min(dp[i][j - wv[i][1]] + wv[i][0], dp[i][j])
        else:
            dp[i+1][j] = min((dp[i][j], dp[i+1][j]))

for i in reversed(list(range(lim))):
    if dp[-1][i] <= w:
        ans = i
        break
print(ans)