it is illegal for a vector to contain
  pointers to invalid memory
This is what the Standard has to say about the contents of a container:
(23.3) : The type of objects stored in these components must meet the requirements of CopyConstructible types (20.1.3), and the additional requirements of Assignable types.
(20.1.3.1, CopyConstructible) : In the following Table 30, T is a type to be supplied by a C + + program instantiating a template, t is a value of type T, and u is a value of type const T.
expression  return type  requirement
xxxxxxxxxx    xxxxxxxxxxx  xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
T(t)                       t is equivelant to T(t)
T(u)                       u is equivelant to T(u)
t.~T()      
&t          T*           denotes the address of t
&u          const T*     denotes the address of u
(23.1.4, Assignable) : 64, T is the type used to instantiate the container, t is a value of T, and u is a value of (possibly
const) T.
expression  return type  requirement
xxxxxxxxxx    xxxxxxxxxxx  xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
t = u         T&           t is equivilant to u
That's all that is says about the contents of an STL collection.  It says nothing about pointers and it is particularly silent about the pointers pointing to valid memory.
Therefore, deleteing pointers in a vector, while most likely a very bad architectural decision and an invitation to pain and suffering with the debugger at 3:00 AM on a Saturday night, is perfectly legal.
EDIT:
Regarding Kranar's comment that "assigning a pointer to an invalid pointer value results in undefined behavior."  No, this is incorrect.  This code is perfectly valid:
Foo* foo = new Foo();
delete foo;
Foo* foo_2 = foo;  // This is legal
What is illegal is trying to do something with that pointer (or foo, for that matter):
delete foo_2; // UB
foo_2->do_something(); // UB
Foo& foo_ref = *foo_2; // UB
Simply creating a wild pointer is legal according to the Standard.  Probably not a good idea, but legal nonetheless.
EDIT2:
More from the Standard regarding pointer types.  
So sayeth the Standard (3.9.2.3) :
  ... A valid value of an object pointer
  type represents either the address of
  a byte in memory (1.7) or a null
  pointer (4.10)...
...and regarding "a byte in memory," (1.7.1) :
  The fundamental storage unit in the C
  + + memory model is the byte. A byte is at least large enough to contain
  any member of the basic execution
  character set and is composed of a
  contiguous sequence of bits, the
  number of which is
  implementation-defined. The least
  significant bit is called the
  low-order bit; the most significant
  bit is called the high-order bit. The
  memory available to a C + + program
  consists of one or more sequences of
  contiguous bytes. Every byte has a
  unique address.
There is nothing here about that byte being part of a living Foo, about you having access to it, or anything of the sort.  Its just a byte in memory.