Input iterators are used to iterate over ranges that don't have a material realization (id est their elements do not actually exist somewhere in memory), like bytes from a network stream, or a sequence of random numbers from /dev/random. Consider this last example: once you consume the first random number, there is no way to retrieve it again.
Forward iterators, on the other hand, provide access to ranges that either have a material realization (id est all their elements actually exist somewhere in memory) or that can be easily recomputed†. By their very nature, containers usually provide forward iterators: the containers themselves are the materialization of the range.
Ranges defined with input iterators can sometimes be converted to a range define with forward iterators, by simply materializing it: just use the single pass to copy the whole range into a container, and then iterate on that container as much as you like. Obviously this won't be desirable in all situations, and sometimes it is not even possible: some ranges, like the bytes from /dev/random, are infinite and can never be materialized in full.
If an algorithm can be written in a single pass, there is no reason to forbid its use with input iterators. However, there is nothing that forbids such an algorithm from using an optimised version that performs multiple passes, when given forward or better iterators.
† For instance, a range of all the even numbers does not need to materialize all numbers in a container, but one can easily start again from a given iterator since it is possible and cheap to recompute the numbers again.