Iterating pattern (1-10 then 10-1) with only 1 loop
I don't see any compelling reason for doing this in one loop, but it's certainly possible in a simpler way.  First, though let's look at some other aspects of the code.

Declare one variable per line

Generally, it's better for readability if we declare just one variable per line instead of cramming them all together on a single line.

Use more whitespace

Lines like this 

while(i!=0 &amp;&amp; lines&lt;3){


Are rendered much more readable if we use more whitespace:

while (i != 0 &amp;&amp; lines &lt; 3) {


Use braces consistently

I'd recommend using braces around the else clause statement, even though it isn't technically required.  In addition to making things more readable (there's that word again!) it helps to prevent bugs.

Use better variable names

In the current code, lines is a good variable name because it suggests the purpose of the variable, but flag is not a very good name.  It would be better to make it bool and call it reverse.

Use named constants

Named constants make it easier for readers of the program to understand what's being done and why.  

Simplify your code

Essentially, what the program is intended to do is make three traversals from 1 to 10 and back.  I'd write it like this:

int main(void) {
    const int lowerlimit = 1;
    const int upperlimit = 10;
    int i = lowerlimit; 
    int delta = +1;  // start counting up
    for (int traversals=3; traversals; ) {
        printf("%d ", i);
        i += delta;
        if (i &gt; upperlimit || i &lt; lowerlimit) {
            printf("\n");
            delta *= -1;   // change direction
            i += delta;    // come back in bounds
            --traversals;
        }
    }
}


Omit return 0

When a C or C++ program reaches the end of main the compiler will automatically generate code to return 0, so there is no need to put return 0; explicitly at the end of main.  

Note: when I make this suggestion, it's almost invariably followed by one of two kinds of comments:  "I didn't know that." or "That's bad advice!"  My rationale is that it's safe and useful to rely on compiler behavior explicitly supported by the standard.  For C, since C99; see ISO/IEC 9899:1999 section 5.1.2.2.3:


  [...] a return from the initial call to the main function is equivalent to calling the exit function with the value returned by the main function as its argument; reaching the } that terminates the main function returns a value of 0.


For C++, since the first standard in 1998; see ISO/IEC 14882:1998 section 3.6.1:


  If control reaches the end of main without encountering a return statement, the effect is that of executing return 0;


All versions of both standards since then (C99 and C++98) have maintained the same idea.  We rely on automatically generated member functions in C++, and few people write explicit return; statements at the end of a void function.  Reasons against omitting seem to boil down to "it looks weird".  If, like me, you're curious about the rationale for the change to the C standard read this question.  Also note that in the early 1990s this was considered "sloppy practice" because it was undefined behavior (although widely supported) at the time.  

So I advocate omitting it; others disagree (often vehemently!)  In any case, if you encounter code that omits it, you'll know that it's explicitly supported by the standard and you'll know what it means.