the n+1 comes from the execution module of the reference implementation if you use the "default/simple" logic.
But this is just a reference/general purpose implementation.
No one said you can not create smarter resolvers that inspect the AST or even create your own execution module. It's possible :) and it works.
I find this strange, because this has been a solved problem with graphql-js for about 18 months now, and provided as a core feature in other implementations such as Sangria in Scala. I've written about this particular problem, calling out solutions that exist in different languages: