That assignment should be
Code:
*flights = malloc((size_t)*num_flights*sizeof(Flight));
You shouldn't need to cast malloc, unless you're using C++ all of a sudden. And you don't want to change the value of flights -- that's a local variable, and any changes made to it will vanish when you get back to main. You want to change the value of the variable pointed to.

It doesn't look marvelous, I admit, but I don't know that you can get rid of much: the & is required when dealing with scanf, the .number tag is necessary so we know what part of the struct we're looking at.

As to (*flights)[i], if you want to make it look cleaner you can move the ugliness to somewhere else. You might consider borrowing the iterator idea from C++, and have an extra Flight* pointer (call it flight_iterator, or the like) -- your flight number becomes flight_iterator->number (since flight_iterator is a pointer, you need the arrow to get at the member of the struct pointed to) and doing flight_iterator++ will move you to the next Flight in line. All the bits are still there, somewhere, it's just more spread out.