NULL (or more correctly, since you tagged C++11, nullptr) is used for checking pointers. You've declared a vector of concrete instances, so pointers don't apply, and if the test
if (i < edges.size())
then the vector is initialized - that is, constructed. You can check, next, whether it is populated:
if (i < edges.size() && !edges[i].empty())
however, this will not distinguish between uninitialized and currently empty, consider:
std::vector<int> v; v.push_back(1); v.pop_back(); // now it's empty again bool uninitialized = v.empty(); // lies
It is empty, but it has been initialized and used, if that is your definition of initialized.
There is, however, one trick left, but it is tending towards undefined behavior.
if (i < edges.size() && edges[i].capacity() == 0)
This will tell you if the vector has any memory allocated. In the worst case scenario, if your vector aggressively frees, it will be equivalent to empty(). But in most standard implementations, a vector that has been populated will have non-zero capacity, whilst a vector that has not yet been used will have no capacity.
Again: it's not perfect, there are ways to tell the vector to release any capacity it has.
NULLdoes not make sense. No offense, but you should learn the basics of objects, references and pointers in C++.vector<vector<int> > edgessimply exists within its scope. Take more time to express yourself.