#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <algorithm>
#include <vector>
#include <deque>
#include <set>
#include <map>
#include <functional>
#include <hash_set>

// Types definition
//
typedef signed char                 int8;
typedef unsigned char               uint8;
typedef signed short                int16;
typedef unsigned short              uint16;
typedef signed long                 int32;
typedef unsigned long               uint32;
typedef signed long long            int64;
typedef unsigned long long          uint64;

typedef std::vector<size_t>         SizeTVector;
typedef std::set<size_t>            SizeTSet;
typedef std::multiset<size_t>       SizeTMultiset;

typedef std::vector<std::string>    StringVector;
typedef std::set<std::string>       StringSet;
typedef std::multiset<std::string>  StringMultiset;

// Auxiliary functions definition
//
inline void DoNothing() { }
template<typename T> inline T Abs(const T a) { return a < 0 ? -a : a; }
template<typename T> inline T Min(const T a, const T b) {return a < b ? a : b;}
template<typename T> inline T Max(const T a, const T b) {return a > b ? a : b;}

static const double eps = 1.0e-8;
inline double IsEqual(const double a, const double b) { return Abs(a - b) < eps; }
inline double IsGreater(const double a, const double b) { return a > b + eps; }
inline double IsLess(const double a, const double b) { return a + eps < b; }

struct Rand
{
    uint32 z_, w_;
    uint32 get32() { z_ = 36969 * (z_ & 65535) + (z_ >> 16); w_ = 18000 * (w_ & 65535) + (w_ >> 16); return (z_ << 16) + (w_ & 65535); }
    void Reset() { z_ = 1; w_ = 1; }
    Rand() { Reset(); }
};

template <typename T> inline std::vector<std::vector<T> > CreateVector2d(const size_t rowCnt, const size_t colCnt)
{
    return std::vector<std::vector<T> > (rowCnt, std::vector<T>(colCnt));
}

#ifndef ONLINE_JUDGE
#define PRINT(a) std::cout << '\t' << #a << " = " << (a) << "; "
#define NEWLINE() std::cout << std::endl;
#else //ONLINE_JUDGE
#define PRINT(a) DoNothing()
#define NEWLINE() DoNothing()
#endif //ONLINE_JUDGE

// Auxiliary functions forward definition
//
void Prepare();

class StopWatchEx
{
public:
    StopWatchEx();
    ~StopWatchEx();

private:
    struct Data;
    Data *pData;
};

// Local functions definition
//

typedef stdext::hash_set<size_t>                SizeTHashSet;
typedef std::vector<std::vector<size_t> >       SizeTVector2d;
typedef std::vector<std::set<size_t> >          SizeTSetVector;
typedef std::vector<std::vector<SizeTHashSet> > HashSetVector2d;

struct Edge
{
    size_t from;
    size_t to;
    size_t minWayPrev;
    Edge(const size_t _from, const size_t _to, const size_t _minWayPrev): from(_from), to(_to), minWayPrev(_minWayPrev) {}
};

typedef std::deque<Edge>                        EdgeDeque;

template<typename T>
inline bool IsFound(const stdext::hash_set<T>& container, const T val)
{
    return (container.find(val) != container.end());
}

bool Solve(bool bCheckInputStream = false)
{
    // First input operation
    //
    size_t n, m, k;
    std::cin >> n >> m >> k;

    if (bCheckInputStream && !std::cin)
    {
        return false;
    }

    StopWatchEx _sw;

    SizeTVector2d links(n);
    SizeTSetVector linked(n);
    HashSetVector2d forbidden = CreateVector2d<SizeTHashSet>(n, n);
    // Other input operations and calculations
    //

    for (size_t i = 0; i < m; ++i)
    {
        size_t x, y;
        std::cin >> x >> y;
        --x; --y;
        links[x].push_back(y);
        links[y].push_back(x);
        linked[x].insert(y);
        linked[y].insert(x);
    }

    for (size_t i = 0; i < k; ++i)
    {
        size_t a, b, c;
        std::cin >> a >> b >> c;
        --a; --b; --c;
        forbidden[a][b].insert(c);
    }

    SizeTVector2d be = CreateVector2d<size_t>(n, n);
    SizeTVector2d minWay = CreateVector2d<size_t>(n, n);

    const size_t startId = 0;
    const size_t stopId = n-1;

    EdgeDeque queue;
    // first step
    for(size_t i = 0; i < n; i++)
    {
        minWay[i][startId] = 0;
        be[i][startId] = 1;
    }
    for(size_t i = 0; i < links[startId].size(); ++i)
    {
        queue.push_back(Edge(startId, links[startId][i], 0));
    }

    // other steps
    while (!queue.empty())
    {
        const size_t queueSize = queue.size();

        for (size_t i = 0; i < queueSize; i++)
        {
            const Edge& nextEdge = queue.at(0);
            const size_t nextId = nextEdge.to;

            if (!be[nextEdge.from][nextEdge.to] ||
                minWay[nextEdge.from][nextEdge.to] > nextEdge.minWayPrev + 1)
            {
                be[nextEdge.from][nextEdge.to] = true;
                minWay[nextEdge.from][nextEdge.to] = nextEdge.minWayPrev + 1;

                for (size_t i = 0; i < links[nextId].size(); i++)
                {
                    const size_t nextNextId = links[nextId][i];
                    if (!be[nextEdge.to][nextNextId])
                    {
                        if (!IsFound(forbidden[nextEdge.from][nextEdge.to], nextNextId))
                        {
                            queue.push_back(Edge(nextEdge.to, nextNextId, minWay[nextEdge.from][nextEdge.to]));
                        }
                    }
                }
            }
            queue.pop_front();
        }
    }

    SizeTVector sequence;
    bool bFound = false;
    static const size_t UNKNOWN = 0xFFFFFFFFUL;
    size_t stepsLeft = UNKNOWN;
    size_t curId = UNKNOWN;
    for (size_t i = 0; i < n; ++i)
    {
        if (be[i][stopId] && (!bFound || stepsLeft > minWay[i][stopId]))
        {
            bFound = true;
            stepsLeft = minWay[i][stopId];
            curId = i;
        }
    }

    if (bFound)
    {
        curId = stopId;
        while (stepsLeft != 0)
        {
            for (size_t i = 0; i < n; i++)
            {
                if (be[i][curId] && minWay[i][curId] == stepsLeft)
                {
                    if (linked[i].find(curId) != linked[i].end())
                    {
                        sequence.push_back(i);
                        curId = i;
                        break;
                    }
                }
            }
            --stepsLeft;
        }

        std::reverse(sequence.begin(), sequence.end());

        std::cout << sequence.size() << std::endl;
        for(size_t i = 0; i < sequence.size(); ++i)
        {
            std::cout << sequence[i] + 1 << ' ';
        }
        std::cout << n << std::endl;
    }
    else
    {
        std::cout << "-1" << std::endl;
    }

    return true;
    // End of all calculations
}

int main()
{
    Prepare();

#if defined(ONLINE_JUDGE)
    Solve();
#else //defined(ONLINE_JUDGE)
    //while (Solve(true))   { }
    Solve();
#endif //defined(ONLINE_JUDGE)
}

// Test-specific stuff

#if !defined(ONLINE_JUDGE)
#endif // !defined(ONLINE_JUDGE)

#if !defined(ONLINE_JUDGE)
#include <windows.h>
#endif //!defined(ONLINE_JUDGE)

struct StopWatchEx::Data
{
#if !defined(ONLINE_JUDGE)
    FILETIME timeStartSystem;
    FILETIME timeStartUser;
#endif //!defined(ONLINE_JUDGE)
};

StopWatchEx::StopWatchEx()
{
#if !defined(ONLINE_JUDGE)
    pData = new Data();
    FILETIME dummy;
    GetProcessTimes(GetCurrentProcess(), &dummy, &dummy, &dummy, &pData->timeStartUser);
    GetSystemTimeAsFileTime(&pData->timeStartSystem);
#endif //!defined(ONLINE_JUDGE)
}

#if !defined(ONLINE_JUDGE)
ULONGLONG FileTimeToU64(const FILETIME& time)
{
    return ((ULONGLONG)time.dwHighDateTime << 32) | time.dwLowDateTime;
}

ULONGLONG GetTimeDiffMs(const FILETIME& first, const FILETIME& second)
{
    return ((FileTimeToU64(first) - FileTimeToU64(second)) + 9999) / 10000;
}
#endif // !defined(ONLINE_JUDGE)

StopWatchEx::~StopWatchEx()
{
#if !defined(ONLINE_JUDGE)
    FILETIME timeCreated;
    FILETIME timeStopUser;
    FILETIME dummy;
    GetProcessTimes(GetCurrentProcess(), &timeCreated, &dummy, &dummy, &timeStopUser);

    FILETIME timeCurrent;
    GetSystemTimeAsFileTime(&timeCurrent);

    std::cout << std::setw(20) << "Total process = " << GetTimeDiffMs(timeCurrent, timeCreated) << " ms" << std::endl;
    std::cout << std::setw(20) << "UserTime diff = " << GetTimeDiffMs(timeStopUser, pData->timeStartUser) << " ms" << std::endl;
    std::cout << std::setw(20) << "SysTime diff = " << GetTimeDiffMs(timeCurrent, pData->timeStartSystem) << " ms" << std::endl;
    std::cout << std::endl;

    delete pData;
#endif //!defined(ONLINE_JUDGE)
}

void Prepare()
{
#if !defined(ONLINE_JUDGE)
    SetProcessAffinityMask(GetCurrentProcess(), 1);
#endif //!defined(ONLINE_JUDGE)
}


#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <algorithm>
#include <vector>
#include <deque>
#include <set>
#include <map>
#include <functional>
#include <hash_set>

// Types definition
//
typedef signed char                 int8;
typedef unsigned char               uint8;
typedef signed short                int16;
typedef unsigned short              uint16;
typedef signed long                 int32;
typedef unsigned long               uint32;
typedef signed long long            int64;
typedef unsigned long long          uint64;

typedef std::vector<size_t>         SizeTVector;
typedef std::set<size_t>            SizeTSet;
typedef std::multiset<size_t>       SizeTMultiset;

typedef std::vector<std::string>    StringVector;
typedef std::set<std::string>       StringSet;
typedef std::multiset<std::string>  StringMultiset;

// Auxiliary functions definition
//
inline void DoNothing() { }
template<typename T> inline T Abs(const T a) { return a < 0 ? -a : a; }
template<typename T> inline T Min(const T a, const T b) {return a < b ? a : b;}
template<typename T> inline T Max(const T a, const T b) {return a > b ? a : b;}

static const double eps = 1.0e-8;
inline double IsEqual(const double a, const double b) { return Abs(a - b) < eps; }
inline double IsGreater(const double a, const double b) { return a > b + eps; }
inline double IsLess(const double a, const double b) { return a + eps < b; }

struct Rand
{
    uint32 z_, w_;
    uint32 get32() { z_ = 36969 * (z_ & 65535) + (z_ >> 16); w_ = 18000 * (w_ & 65535) + (w_ >> 16); return (z_ << 16) + (w_ & 65535); }
    void Reset() { z_ = 1; w_ = 1; }
    Rand() { Reset(); }
};

template <typename T> inline std::vector<std::vector<T> > CreateVector2d(const size_t rowCnt, const size_t colCnt)
{
    return std::vector<std::vector<T> > (rowCnt, std::vector<T>(colCnt));
}

#ifndef ONLINE_JUDGE
#define PRINT(a) std::cout << '\t' << #a << " = " << (a) << "; "
#define NEWLINE() std::cout << std::endl;
#else //ONLINE_JUDGE
#define PRINT(a) DoNothing()
#define NEWLINE() DoNothing()
#endif //ONLINE_JUDGE

// Auxiliary functions forward definition
//
void Prepare();

class StopWatchEx
{
public:
    StopWatchEx();
    ~StopWatchEx();

private:
    struct Data;
    Data *pData;
};

// Local functions definition
//
typedef uint16  VertexId;
typedef stdext::hash_set<VertexId>              VertexHashSet;
typedef std::vector<VertexId>                   VertexVector;
typedef std::vector<std::vector<VertexId> >     VertexVector2d;

struct DataField
{
    uint16 be;
    uint32 minWay;

    DataField(): be(0), minWay(0) {}
};

typedef std::vector<std::vector<DataField> >    DataFieldVector2d;

struct TwoPoints
{
    VertexId a, b;

    bool operator<(const TwoPoints& rval) const
    {
        if (a < rval.a) { return true; }
        else if (rval.a < a) { return false; }
        else { return b < rval.b; }
    }

    TwoPoints(const VertexId _a, const VertexId _b): a(_a), b(_b) {}
};

typedef std::map<TwoPoints, VertexHashSet>      MapEdgeToVertexSet;

typedef stdext::hash_set<size_t>                SizeTHashSet;
typedef std::vector<std::vector<size_t> >       SizeTVector2d;
typedef std::vector<std::set<size_t> >          SizeTSetVector;
typedef std::vector<std::vector<SizeTHashSet> > HashSetVector2d;

struct Edge
{
    VertexId from;
    VertexId to;
    uint32 minWayPrev;
    Edge(const VertexId _from, const VertexId _to, const uint32 _minWayPrev): from(_from), to(_to), minWayPrev(_minWayPrev) {}
};

typedef std::deque<Edge>                        EdgeDeque;

template<typename T>
inline bool IsFound(const stdext::hash_set<T>& container, const T val)
{
    return (container.find(val) != container.end());
}

inline bool IsForbidden(const MapEdgeToVertexSet& mapping, const TwoPoints& ab, const VertexId c)
{
    MapEdgeToVertexSet::const_iterator pI = mapping.find(ab);
    if (pI != mapping.end() &&
        pI->second.find(c) != pI->second.end())
    {
        return true;
    }
    else
    {
        return false;
    }
}

inline bool IsForbidden(const MapEdgeToVertexSet& mapping, const VertexId a, const VertexId b, const VertexId c)
{
    return IsForbidden(mapping, TwoPoints(a, b), c);
}

inline bool IsLinked(const VertexVector2d& linksSorted, const VertexId a, const VertexId b)
{
    const VertexVector& links_a = linksSorted[a];
    return std::binary_search(links_a.begin(), links_a.end(), b);
}

bool Solve(bool bCheckInputStream = false)
{
    // First input operation
    //
    VertexId n;
    size_t m, k;
    std::cin >> n >> m >> k;

    if (bCheckInputStream && !std::cin)
    {
        return false;
    }

    //StopWatchEx _sw;

    VertexVector2d links(n);
    MapEdgeToVertexSet forbidden;
    // Other input operations and calculations
    //

    for (size_t i = 0; i < m; ++i)
    {
        VertexId x, y;
        std::cin >> x >> y;
        --x; --y;
        links[x].push_back(y);
        links[y].push_back(x);
    }

    for (VertexId i = 0; i < n; i++)
    {
        std::sort(links[i].begin(), links[i].end());
    }

    for (size_t i = 0; i < k; ++i)
    {
        VertexId a, b, c;
        std::cin >> a >> b >> c;
        --a; --b; --c;
        forbidden[TwoPoints(a, b)].insert(c);
    }

    DataFieldVector2d data = CreateVector2d<DataField>(n, n);

    const VertexId startId = 0;
    const VertexId stopId = n-1;

    EdgeDeque queue;
    // first step
    for(size_t i = 0; i < n; i++)
    {
        data[i][startId].minWay = 0;
        data[i][startId].be = 1;
    }
    for(size_t i = 0; i < links[startId].size(); ++i)
    {
        queue.push_back(Edge(startId, links[startId][i], 0));
    }

    // other steps
    while (!queue.empty())
    {
        const size_t queueSize = queue.size();

        bool bStopFound = false;
        for (size_t i = 0; i < queueSize && !bStopFound; i++)
        {
            const Edge nextEdge = queue.at(0);
            queue.pop_front();

            if (!data[nextEdge.from][nextEdge.to].be)
            {
                data[nextEdge.from][nextEdge.to].be = 1;
                data[nextEdge.from][nextEdge.to].minWay = nextEdge.minWayPrev + 1;

                if (nextEdge.to == stopId)
                {
                    bStopFound = true;
                }
                else
                {
                    for (size_t i = 0; i < links[nextEdge.to].size(); i++)
                    {
                        const VertexId nextNextId = links[nextEdge.to][i];
                        if (!data[nextEdge.to][nextNextId].be)
                        {
                            if (!IsForbidden(forbidden, TwoPoints(nextEdge.from, nextEdge.to), nextNextId))
                            {
                                queue.push_back(Edge(nextEdge.to, nextNextId, data[nextEdge.from][nextEdge.to].minWay));
                            }
                        }
                    }
                }
            }
        }

        if (bStopFound)
        {
            break;
        }
    }

    VertexVector sequence;
    bool bReached = false;
    uint32 stepCnt = 0;

    for (size_t i = 0; i < n; ++i)
    {
        if (data[i][stopId].be && (!bReached || data[i][stopId].minWay < stepCnt))
        {
            bReached = true;
            stepCnt = data[i][stopId].minWay;
        }
    }

    if (bReached)
    {
        VertexId curId = stopId;
        sequence.push_back(curId);

        while (curId != startId)
        {
            bool bNextStepFound = false;
            VertexId prevId = 0;
            for (VertexId i = 0; i < n; ++i)
            {
                if (IsLinked(links, i, curId) && data[i][curId].minWay == stepCnt)
                {
                    bNextStepFound = true;
                    prevId = i;
                    break;
                }
            }
            if (!bNextStepFound)
            {
                break;
            }

            curId = prevId;
            sequence.push_back(curId);
            --stepCnt;
        }

        std::reverse(sequence.begin(), sequence.end());

        std::cout << sequence.size() - 1 << std::endl;
        for(size_t i = 0; i < sequence.size(); ++i)
        {
            std::cout << sequence[i] + 1 << ' ';
        }
        std::cout << std::endl;
    }
    else
    {
        std::cout << "-1" << std::endl;
    }

    return true;
    // End of all calculations
}

int main()
{
    Prepare();

#if defined(ONLINE_JUDGE)
    Solve();
#else //defined(ONLINE_JUDGE)
    while (Solve(true)) { }
    //Solve();
#endif //defined(ONLINE_JUDGE)
}

// Test-specific stuff

#if !defined(ONLINE_JUDGE)
#endif // !defined(ONLINE_JUDGE)

#if !defined(ONLINE_JUDGE)
#include <windows.h>
#endif //!defined(ONLINE_JUDGE)

struct StopWatchEx::Data
{
#if !defined(ONLINE_JUDGE)
    FILETIME timeStartSystem;
    FILETIME timeStartUser;
#endif //!defined(ONLINE_JUDGE)
};

StopWatchEx::StopWatchEx()
{
#if !defined(ONLINE_JUDGE)
    pData = new Data();
    FILETIME dummy;
    GetProcessTimes(GetCurrentProcess(), &dummy, &dummy, &dummy, &pData->timeStartUser);
    GetSystemTimeAsFileTime(&pData->timeStartSystem);
#endif //!defined(ONLINE_JUDGE)
}

#if !defined(ONLINE_JUDGE)
ULONGLONG FileTimeToU64(const FILETIME& time)
{
    return ((ULONGLONG)time.dwHighDateTime << 32) | time.dwLowDateTime;
}

ULONGLONG GetTimeDiffMs(const FILETIME& first, const FILETIME& second)
{
    return ((FileTimeToU64(first) - FileTimeToU64(second)) + 9999) / 10000;
}
#endif // !defined(ONLINE_JUDGE)

StopWatchEx::~StopWatchEx()
{
#if !defined(ONLINE_JUDGE)
    FILETIME timeCreated;
    FILETIME timeStopUser;
    FILETIME dummy;
    GetProcessTimes(GetCurrentProcess(), &timeCreated, &dummy, &dummy, &timeStopUser);

    FILETIME timeCurrent;
    GetSystemTimeAsFileTime(&timeCurrent);

    std::cout << std::setw(20) << "Total process = " << GetTimeDiffMs(timeCurrent, timeCreated) << " ms" << std::endl;
    std::cout << std::setw(20) << "UserTime diff = " << GetTimeDiffMs(timeStopUser, pData->timeStartUser) << " ms" << std::endl;
    std::cout << std::setw(20) << "SysTime diff = " << GetTimeDiffMs(timeCurrent, pData->timeStartSystem) << " ms" << std::endl;
    std::cout << std::endl;

    delete pData;
#endif //!defined(ONLINE_JUDGE)
}

void Prepare()
{
#if !defined(ONLINE_JUDGE)
    SetProcessAffinityMask(GetCurrentProcess(), 1);
#endif //!defined(ONLINE_JUDGE)
}


#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <algorithm>
#include <vector>
#include <deque>
#include <set>
#include <map>
#include <functional>
#include <hash_set>

// Types definition
//
typedef signed char                 int8;
typedef unsigned char               uint8;
typedef signed short                int16;
typedef unsigned short              uint16;
typedef signed long                 int32;
typedef unsigned long               uint32;
typedef signed long long            int64;
typedef unsigned long long          uint64;

typedef std::vector<size_t>         SizeTVector;
typedef std::set<size_t>            SizeTSet;
typedef std::multiset<size_t>       SizeTMultiset;

typedef std::vector<std::string>    StringVector;
typedef std::set<std::string>       StringSet;
typedef std::multiset<std::string>  StringMultiset;

// Auxiliary functions definition
//
inline void DoNothing() { }
template<typename T> inline T Abs(const T a) { return a < 0 ? -a : a; }
template<typename T> inline T Min(const T a, const T b) {return a < b ? a : b;}
template<typename T> inline T Max(const T a, const T b) {return a > b ? a : b;}

static const double eps = 1.0e-8;
inline double IsEqual(const double a, const double b) { return Abs(a - b) < eps; }
inline double IsGreater(const double a, const double b) { return a > b + eps; }
inline double IsLess(const double a, const double b) { return a + eps < b; }

struct Rand
{
    uint32 z_, w_;
    uint32 get32() { z_ = 36969 * (z_ & 65535) + (z_ >> 16); w_ = 18000 * (w_ & 65535) + (w_ >> 16); return (z_ << 16) + (w_ & 65535); }
    void Reset() { z_ = 1; w_ = 1; }
    Rand() { Reset(); }
};

template <typename T> inline std::vector<std::vector<T> > CreateVector2d(const size_t rowCnt, const size_t colCnt)
{
    return std::vector<std::vector<T> > (rowCnt, std::vector<T>(colCnt));
}

#ifndef ONLINE_JUDGE
#define PRINT(a) std::cout << '\t' << #a << " = " << (a) << "; "
#define NEWLINE() std::cout << std::endl;
#else //ONLINE_JUDGE
#define PRINT(a) DoNothing()
#define NEWLINE() DoNothing()
#endif //ONLINE_JUDGE

// Auxiliary functions forward definition
//
void Prepare();

class StopWatchEx
{
public:
    StopWatchEx();
    ~StopWatchEx();

private:
    struct Data;
    Data *pData;
};

// Local functions definition
//
typedef uint16  VertexId;
typedef stdext::hash_set<VertexId>              VertexHashSet;
typedef std::vector<VertexId>                   VertexVector;
typedef std::vector<std::vector<VertexId> >     VertexVector2d;

struct DataField
{
    uint16 be;
    uint32 minWay;

    DataField(): be(0), minWay(0) {}
};

typedef std::vector<std::vector<DataField> >    DataFieldVector2d;

struct TwoPoints
{
    VertexId a, b;

    bool operator<(const TwoPoints& rval) const
    {
        if (a < rval.a) { return true; }
        else if (rval.a < a) { return false; }
        else { return b < rval.b; }
    }

    TwoPoints(const VertexId _a, const VertexId _b): a(_a), b(_b) {}
};

typedef std::map<TwoPoints, VertexHashSet>      MapEdgeToVertexSet;

typedef stdext::hash_set<size_t>                SizeTHashSet;
typedef std::vector<std::vector<size_t> >       SizeTVector2d;
typedef std::vector<std::set<size_t> >          SizeTSetVector;
typedef std::vector<std::vector<SizeTHashSet> > HashSetVector2d;

struct Edge
{
    VertexId from;
    VertexId to;
    uint32 minWayPrev;
    Edge(const VertexId _from, const VertexId _to, const uint32 _minWayPrev): from(_from), to(_to), minWayPrev(_minWayPrev) {}
};

typedef std::deque<Edge>                        EdgeDeque;

template<typename T>
inline bool IsFound(const stdext::hash_set<T>& container, const T val)
{
    return (container.find(val) != container.end());
}

inline bool IsForbidden(const MapEdgeToVertexSet& mapping, const TwoPoints& ab, const VertexId c)
{
    MapEdgeToVertexSet::const_iterator pI = mapping.find(ab);
    if (pI != mapping.end() &&
        pI->second.find(c) != pI->second.end())
    {
        return true;
    }
    else
    {
        return false;
    }
}

inline bool IsForbidden(const MapEdgeToVertexSet& mapping, const VertexId a, const VertexId b, const VertexId c)
{
    return IsForbidden(mapping, TwoPoints(a, b), c);
}

inline bool IsLinked(const VertexVector2d& linksSorted, const VertexId a, const VertexId b)
{
    const VertexVector& links_a = linksSorted[a];
    return std::binary_search(links_a.begin(), links_a.end(), b);
}

bool Solve(bool bCheckInputStream = false)
{
    // First input operation
    //
    VertexId n;
    size_t m, k;
    std::cin >> n >> m >> k;

    if (bCheckInputStream && !std::cin)
    {
        return false;
    }

    StopWatchEx _sw;

    VertexVector2d links(n);
    MapEdgeToVertexSet forbidden;
    // Other input operations and calculations
    //

    for (size_t i = 0; i < m; ++i)
    {
        VertexId x, y;
        std::cin >> x >> y;
        --x; --y;
        links[x].push_back(y);
        links[y].push_back(x);
    }

    for (VertexId i = 0; i < n; i++)
    {
        std::sort(links[i].begin(), links[i].end());
    }

    for (size_t i = 0; i < k; ++i)
    {
        VertexId a, b, c;
        std::cin >> a >> b >> c;
        --a; --b; --c;
        forbidden[TwoPoints(a, b)].insert(c);
    }

    DataFieldVector2d data = CreateVector2d<DataField>(n, n);

    const VertexId startId = 0;
    const VertexId stopId = n-1;

    EdgeDeque queue;
    // first step
    for(size_t i = 0; i < n; i++)
    {
        data[i][startId].minWay = 0;
        data[i][startId].be = 1;
    }
    for(size_t i = 0; i < links[startId].size(); ++i)
    {
        queue.push_back(Edge(startId, links[startId][i], 0));
    }

    // other steps
    while (!queue.empty())
    {
        const size_t queueSize = queue.size();

        for (size_t i = 0; i < queueSize; i++)
        {
            const Edge& nextEdge = queue.at(0);
            const size_t nextId = nextEdge.to;

            if (!data[nextEdge.from][nextEdge.to].be ||
                data[nextEdge.from][nextEdge.to].minWay > nextEdge.minWayPrev + 1)
            {
                data[nextEdge.from][nextEdge.to].be = 1;
                data[nextEdge.from][nextEdge.to].minWay = nextEdge.minWayPrev + 1;

                for (size_t i = 0; i < links[nextId].size(); i++)
                {
                    const VertexId nextNextId = links[nextId][i];
                    if (!data[nextEdge.to][nextNextId].be)
                    {
                        if (!IsForbidden(forbidden, TwoPoints(nextEdge.from, nextEdge.to), nextNextId))
                        {
                            queue.push_back(Edge(nextEdge.to, nextNextId, data[nextEdge.from][nextEdge.to].minWay));
                        }
                    }
                }
            }
            queue.pop_front();
        }
    }

    VertexVector sequence;
    bool bReached = false;
    uint32 stepCnt = 0;

    for (size_t i = 0; i < n; ++i)
    {
        if (data[i][stopId].be && (!bReached || data[i][stopId].minWay < stepCnt))
        {
            bReached = true;
            stepCnt = data[i][stopId].minWay;
        }
    }

    if (bReached)
    {
        VertexId curId = stopId;
        sequence.push_back(curId);

        while (curId != startId)
        {
            bool bNextStepFound = false;
            VertexId prevId = 0;
            for (VertexId i = 0; i < n; ++i)
            {
                if (IsLinked(links, i, curId) && data[i][curId].minWay == stepCnt)
                {
                    bNextStepFound = true;
                    prevId = i;
                    break;
                }
            }
            if (!bNextStepFound)
            {
                break;
            }

            curId = prevId;
            sequence.push_back(curId);
            --stepCnt;
        }

        std::reverse(sequence.begin(), sequence.end());

        std::cout << sequence.size() - 1 << std::endl;
        for(size_t i = 0; i < sequence.size(); ++i)
        {
            std::cout << sequence[i] + 1 << ' ';
        }
    }
    else
    {
        std::cout << "-1" << std::endl;
    }

    return true;
    // End of all calculations
}

int main()
{
    Prepare();

#if defined(ONLINE_JUDGE)
    Solve();
#else //defined(ONLINE_JUDGE)
    while (Solve(true)) { }
    //Solve();
#endif //defined(ONLINE_JUDGE)
}

// Test-specific stuff

#if !defined(ONLINE_JUDGE)
#endif // !defined(ONLINE_JUDGE)

#if !defined(ONLINE_JUDGE)
#include <windows.h>
#endif //!defined(ONLINE_JUDGE)

struct StopWatchEx::Data
{
#if !defined(ONLINE_JUDGE)
    FILETIME timeStartSystem;
    FILETIME timeStartUser;
#endif //!defined(ONLINE_JUDGE)
};

StopWatchEx::StopWatchEx()
{
#if !defined(ONLINE_JUDGE)
    pData = new Data();
    FILETIME dummy;
    GetProcessTimes(GetCurrentProcess(), &dummy, &dummy, &dummy, &pData->timeStartUser);
    GetSystemTimeAsFileTime(&pData->timeStartSystem);
#endif //!defined(ONLINE_JUDGE)
}

#if !defined(ONLINE_JUDGE)
ULONGLONG FileTimeToU64(const FILETIME& time)
{
    return ((ULONGLONG)time.dwHighDateTime << 32) | time.dwLowDateTime;
}

ULONGLONG GetTimeDiffMs(const FILETIME& first, const FILETIME& second)
{
    return ((FileTimeToU64(first) - FileTimeToU64(second)) + 9999) / 10000;
}
#endif // !defined(ONLINE_JUDGE)

StopWatchEx::~StopWatchEx()
{
#if !defined(ONLINE_JUDGE)
    FILETIME timeCreated;
    FILETIME timeStopUser;
    FILETIME dummy;
    GetProcessTimes(GetCurrentProcess(), &timeCreated, &dummy, &dummy, &timeStopUser);

    FILETIME timeCurrent;
    GetSystemTimeAsFileTime(&timeCurrent);

    std::cout << std::setw(20) << "Total process = " << GetTimeDiffMs(timeCurrent, timeCreated) << " ms" << std::endl;
    std::cout << std::setw(20) << "UserTime diff = " << GetTimeDiffMs(timeStopUser, pData->timeStartUser) << " ms" << std::endl;
    std::cout << std::setw(20) << "SysTime diff = " << GetTimeDiffMs(timeCurrent, pData->timeStartSystem) << " ms" << std::endl;
    std::cout << std::endl;

    delete pData;
#endif //!defined(ONLINE_JUDGE)
}

void Prepare()
{
#if !defined(ONLINE_JUDGE)
    SetProcessAffinityMask(GetCurrentProcess(), 1);
#endif //!defined(ONLINE_JUDGE)
}


#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <algorithm>
#include <vector>
#include <deque>
#include <set>
#include <map>
#include <functional>
#include <hash_set>

// Types definition
//
typedef signed char                 int8;
typedef unsigned char               uint8;
typedef signed short                int16;
typedef unsigned short              uint16;
typedef signed long                 int32;
typedef unsigned long               uint32;
typedef signed long long            int64;
typedef unsigned long long          uint64;

typedef std::vector<size_t>         SizeTVector;
typedef std::set<size_t>            SizeTSet;
typedef std::multiset<size_t>       SizeTMultiset;

typedef std::vector<std::string>    StringVector;
typedef std::set<std::string>       StringSet;
typedef std::multiset<std::string>  StringMultiset;

// Auxiliary functions definition
//
inline void DoNothing() { }
template<typename T> inline T Abs(const T a) { return a < 0 ? -a : a; }
template<typename T> inline T Min(const T a, const T b) {return a < b ? a : b;}
template<typename T> inline T Max(const T a, const T b) {return a > b ? a : b;}

static const double eps = 1.0e-8;
inline double IsEqual(const double a, const double b) { return Abs(a - b) < eps; }
inline double IsGreater(const double a, const double b) { return a > b + eps; }
inline double IsLess(const double a, const double b) { return a + eps < b; }

struct Rand
{
    uint32 z_, w_;
    uint32 get32() { z_ = 36969 * (z_ & 65535) + (z_ >> 16); w_ = 18000 * (w_ & 65535) + (w_ >> 16); return (z_ << 16) + (w_ & 65535); }
    void Reset() { z_ = 1; w_ = 1; }
    Rand() { Reset(); }
};

template <typename T> inline std::vector<std::vector<T> > CreateVector2d(const size_t rowCnt, const size_t colCnt)
{
    return std::vector<std::vector<T> > (rowCnt, std::vector<T>(colCnt));
}

#ifndef ONLINE_JUDGE
#define PRINT(a) std::cout << '\t' << #a << " = " << (a) << "; "
#define NEWLINE() std::cout << std::endl;
#else //ONLINE_JUDGE
#define PRINT(a) DoNothing()
#define NEWLINE() DoNothing()
#endif //ONLINE_JUDGE

// Auxiliary functions forward definition
//
void Prepare();

class StopWatchEx
{
public:
    StopWatchEx();
    ~StopWatchEx();

private:
    struct Data;
    Data *pData;
};

// Local functions definition
//
typedef uint16  VertexId;
typedef stdext::hash_set<VertexId>              VertexHashSet;
typedef std::vector<VertexId>                   VertexVector;
typedef std::vector<std::vector<VertexId> >     VertexVector2d;

struct DataField
{
    uint16 be;
    uint32 minWay;

    DataField(): be(0), minWay(0) {}
};

typedef std::vector<std::vector<DataField> >    DataFieldVector2d;

struct TwoPoints
{
    VertexId a, b;

    bool operator<(const TwoPoints& rval) const
    {
        if (a < rval.a) { return true; }
        else if (rval.a < a) { return false; }
        else { return b < rval.b; }
    }

    TwoPoints(const VertexId _a, const VertexId _b): a(_a), b(_b) {}
};

typedef std::map<TwoPoints, VertexHashSet>      MapEdgeToVertexSet;

typedef stdext::hash_set<size_t>                SizeTHashSet;
typedef std::vector<std::vector<size_t> >       SizeTVector2d;
typedef std::vector<std::set<size_t> >          SizeTSetVector;
typedef std::vector<std::vector<SizeTHashSet> > HashSetVector2d;

struct Edge
{
    VertexId from;
    VertexId to;
    uint32 minWayPrev;
    Edge(const VertexId _from, const VertexId _to, const uint32 _minWayPrev): from(_from), to(_to), minWayPrev(_minWayPrev) {}
};

typedef std::deque<Edge>                        EdgeDeque;

template<typename T>
inline bool IsFound(const stdext::hash_set<T>& container, const T val)
{
    return (container.find(val) != container.end());
}

inline bool IsForbidden(const MapEdgeToVertexSet& mapping, const TwoPoints& ab, const VertexId c)
{
    MapEdgeToVertexSet::const_iterator pI = mapping.find(ab);
    if (pI != mapping.end() &&
        pI->second.find(c) != pI->second.end())
    {
        return true;
    }
    else
    {
        return false;
    }
}

inline bool IsForbidden(const MapEdgeToVertexSet& mapping, const VertexId a, const VertexId b, const VertexId c)
{
    return IsForbidden(mapping, TwoPoints(a, b), c);
}

inline bool IsLinked(const VertexVector2d& linksSorted, const VertexId a, const VertexId b)
{
    const VertexVector& links_a = linksSorted[a];
    return std::binary_search(links_a.begin(), links_a.end(), b);
}

bool Solve(bool bCheckInputStream = false)
{
    // First input operation
    //
    VertexId n;
    size_t m, k;
    std::cin >> n >> m >> k;

    if (bCheckInputStream && !std::cin)
    {
        return false;
    }

    StopWatchEx _sw;

    VertexVector2d links(n);
    MapEdgeToVertexSet forbidden;
    // Other input operations and calculations
    //

    for (size_t i = 0; i < m; ++i)
    {
        VertexId x, y;
        std::cin >> x >> y;
        --x; --y;
        links[x].push_back(y);
        links[y].push_back(x);
    }

    for (VertexId i = 0; i < n; i++)
    {
        std::sort(links[i].begin(), links[i].end());
    }

    for (size_t i = 0; i < k; ++i)
    {
        VertexId a, b, c;
        std::cin >> a >> b >> c;
        --a; --b; --c;
        forbidden[TwoPoints(a, b)].insert(c);
    }

    DataFieldVector2d data = CreateVector2d<DataField>(n, n);

    const VertexId startId = 0;
    const VertexId stopId = n-1;

    EdgeDeque queue;
    // first step
    for(size_t i = 0; i < n; i++)
    {
        data[i][startId].minWay = 0;
        data[i][startId].be = 1;
    }
    for(size_t i = 0; i < links[startId].size(); ++i)
    {
        queue.push_back(Edge(startId, links[startId][i], 0));
    }

    // other steps
    while (!queue.empty())
    {
        const size_t queueSize = queue.size();

        for (size_t i = 0; i < queueSize; i++)
        {
            const Edge nextEdge = queue.at(0);
            const size_t nextId = nextEdge.to;
            queue.pop_front();

            if (!data[nextEdge.from][nextEdge.to].be ||
                data[nextEdge.from][nextEdge.to].minWay > nextEdge.minWayPrev + 1)
            {
                data[nextEdge.from][nextEdge.to].be = 1;
                data[nextEdge.from][nextEdge.to].minWay = nextEdge.minWayPrev + 1;

                for (size_t i = 0; i < links[nextId].size(); i++)
                {
                    const VertexId nextNextId = links[nextId][i];
                    if (!data[nextEdge.to][nextNextId].be)
                    {
                        if (!IsForbidden(forbidden, TwoPoints(nextEdge.from, nextEdge.to), nextNextId))
                        {
                            queue.push_back(Edge(nextEdge.to, nextNextId, data[nextEdge.from][nextEdge.to].minWay));
                        }
                    }
                }
            }
        }
    }

    VertexVector sequence;
    bool bReached = false;
    uint32 stepCnt = 0;

    for (size_t i = 0; i < n; ++i)
    {
        if (data[i][stopId].be && (!bReached || data[i][stopId].minWay < stepCnt))
        {
            bReached = true;
            stepCnt = data[i][stopId].minWay;
        }
    }

    if (bReached)
    {
        VertexId curId = stopId;
        sequence.push_back(curId);

        while (curId != startId)
        {
            bool bNextStepFound = false;
            VertexId prevId = 0;
            for (VertexId i = 0; i < n; ++i)
            {
                if (IsLinked(links, i, curId) && data[i][curId].minWay == stepCnt)
                {
                    bNextStepFound = true;
                    prevId = i;
                    break;
                }
            }
            if (!bNextStepFound)
            {
                break;
            }

            curId = prevId;
            sequence.push_back(curId);
            --stepCnt;
        }

        std::reverse(sequence.begin(), sequence.end());

        std::cout << sequence.size() - 1 << std::endl;
        for(size_t i = 0; i < sequence.size(); ++i)
        {
            std::cout << sequence[i] + 1 << ' ';
        }
    }
    else
    {
        std::cout << "-1" << std::endl;
    }

    return true;
    // End of all calculations
}

int main()
{
    Prepare();

#if defined(ONLINE_JUDGE)
    Solve();
#else //defined(ONLINE_JUDGE)
    while (Solve(true)) { }
    //Solve();
#endif //defined(ONLINE_JUDGE)
}

// Test-specific stuff

#if !defined(ONLINE_JUDGE)
#endif // !defined(ONLINE_JUDGE)

#if !defined(ONLINE_JUDGE)
#include <windows.h>
#endif //!defined(ONLINE_JUDGE)

struct StopWatchEx::Data
{
#if !defined(ONLINE_JUDGE)
    FILETIME timeStartSystem;
    FILETIME timeStartUser;
#endif //!defined(ONLINE_JUDGE)
};

StopWatchEx::StopWatchEx()
{
#if !defined(ONLINE_JUDGE)
    pData = new Data();
    FILETIME dummy;
    GetProcessTimes(GetCurrentProcess(), &dummy, &dummy, &dummy, &pData->timeStartUser);
    GetSystemTimeAsFileTime(&pData->timeStartSystem);
#endif //!defined(ONLINE_JUDGE)
}

#if !defined(ONLINE_JUDGE)
ULONGLONG FileTimeToU64(const FILETIME& time)
{
    return ((ULONGLONG)time.dwHighDateTime << 32) | time.dwLowDateTime;
}

ULONGLONG GetTimeDiffMs(const FILETIME& first, const FILETIME& second)
{
    return ((FileTimeToU64(first) - FileTimeToU64(second)) + 9999) / 10000;
}
#endif // !defined(ONLINE_JUDGE)

StopWatchEx::~StopWatchEx()
{
#if !defined(ONLINE_JUDGE)
    FILETIME timeCreated;
    FILETIME timeStopUser;
    FILETIME dummy;
    GetProcessTimes(GetCurrentProcess(), &timeCreated, &dummy, &dummy, &timeStopUser);

    FILETIME timeCurrent;
    GetSystemTimeAsFileTime(&timeCurrent);

    std::cout << std::setw(20) << "Total process = " << GetTimeDiffMs(timeCurrent, timeCreated) << " ms" << std::endl;
    std::cout << std::setw(20) << "UserTime diff = " << GetTimeDiffMs(timeStopUser, pData->timeStartUser) << " ms" << std::endl;
    std::cout << std::setw(20) << "SysTime diff = " << GetTimeDiffMs(timeCurrent, pData->timeStartSystem) << " ms" << std::endl;
    std::cout << std::endl;

    delete pData;
#endif //!defined(ONLINE_JUDGE)
}

void Prepare()
{
#if !defined(ONLINE_JUDGE)
    SetProcessAffinityMask(GetCurrentProcess(), 1);
#endif //!defined(ONLINE_JUDGE)
}


#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <algorithm>
#include <vector>
#include <deque>
#include <set>
#include <map>
#include <functional>
#include <hash_set>

// Types definition
//
typedef signed char                 int8;
typedef unsigned char               uint8;
typedef signed short                int16;
typedef unsigned short              uint16;
typedef signed long                 int32;
typedef unsigned long               uint32;
typedef signed long long            int64;
typedef unsigned long long          uint64;

typedef std::vector<size_t>         SizeTVector;
typedef std::set<size_t>            SizeTSet;
typedef std::multiset<size_t>       SizeTMultiset;

typedef std::vector<std::string>    StringVector;
typedef std::set<std::string>       StringSet;
typedef std::multiset<std::string>  StringMultiset;

// Auxiliary functions definition
//
inline void DoNothing() { }
template<typename T> inline T Abs(const T a) { return a < 0 ? -a : a; }
template<typename T> inline T Min(const T a, const T b) {return a < b ? a : b;}
template<typename T> inline T Max(const T a, const T b) {return a > b ? a : b;}

static const double eps = 1.0e-8;
inline double IsEqual(const double a, const double b) { return Abs(a - b) < eps; }
inline double IsGreater(const double a, const double b) { return a > b + eps; }
inline double IsLess(const double a, const double b) { return a + eps < b; }

struct Rand
{
    uint32 z_, w_;
    uint32 get32() { z_ = 36969 * (z_ & 65535) + (z_ >> 16); w_ = 18000 * (w_ & 65535) + (w_ >> 16); return (z_ << 16) + (w_ & 65535); }
    void Reset() { z_ = 1; w_ = 1; }
    Rand() { Reset(); }
};

template <typename T> inline std::vector<std::vector<T> > CreateVector2d(const size_t rowCnt, const size_t colCnt)
{
    return std::vector<std::vector<T> > (rowCnt, std::vector<T>(colCnt));
}

#ifndef ONLINE_JUDGE
#define PRINT(a) std::cout << '\t' << #a << " = " << (a) << "; "
#define NEWLINE() std::cout << std::endl;
#else //ONLINE_JUDGE
#define PRINT(a) DoNothing()
#define NEWLINE() DoNothing()
#endif //ONLINE_JUDGE

// Auxiliary functions forward definition
//
void Prepare();

class StopWatchEx
{
public:
    StopWatchEx();
    ~StopWatchEx();

private:
    struct Data;
    Data *pData;
};

// Local functions definition
//
typedef uint16  VertexId;
typedef stdext::hash_set<VertexId>              VertexHashSet;
typedef std::vector<VertexId>                   VertexVector;
typedef std::vector<std::vector<VertexId> >     VertexVector2d;

struct DataField
{
    uint16 be;
    uint32 minWay;

    DataField(): be(0), minWay(0) {}
};

typedef std::vector<std::vector<DataField> >    DataFieldVector2d;

struct TwoPoints
{
    VertexId a, b;

    bool operator<(const TwoPoints& rval) const
    {
        if (a < rval.a) { return true; }
        else if (rval.a < a) { return false; }
        else { return b < rval.b; }
    }

    TwoPoints(const VertexId _a, const VertexId _b): a(_a), b(_b) {}
};

typedef std::map<TwoPoints, VertexHashSet>      MapEdgeToVertexSet;

typedef stdext::hash_set<size_t>                SizeTHashSet;
typedef std::vector<std::vector<size_t> >       SizeTVector2d;
typedef std::vector<std::set<size_t> >          SizeTSetVector;
typedef std::vector<std::vector<SizeTHashSet> > HashSetVector2d;

struct Edge
{
    VertexId from;
    VertexId to;
    uint32 minWayPrev;
    const Edge* pPrevEdge;

    Edge();
    Edge(const VertexId _from, const VertexId _to, const uint32 _minWayPrev, const Edge* _pPrevEdge = NULL): from(_from), to(_to), minWayPrev(_minWayPrev), pPrevEdge(_pPrevEdge) {}
};

//typedef std::deque<Edge>                      EdgeDeque;
typedef std::list<Edge>                         EdgeList;

template<typename T>
inline bool IsFound(const stdext::hash_set<T>& container, const T val)
{
    return (container.find(val) != container.end());
}

inline bool IsForbidden(const MapEdgeToVertexSet& mapping, const TwoPoints& ab, const VertexId c)
{
    MapEdgeToVertexSet::const_iterator pI = mapping.find(ab);
    if (pI != mapping.end() &&
        pI->second.find(c) != pI->second.end())
    {
        return true;
    }
    else
    {
        return false;
    }
}

inline bool IsForbidden(const MapEdgeToVertexSet& mapping, const VertexId a, const VertexId b, const VertexId c)
{
    return IsForbidden(mapping, TwoPoints(a, b), c);
}

inline bool IsLinked(const VertexVector2d& linksSorted, const VertexId a, const VertexId b)
{
    const VertexVector& links_a = linksSorted[a];
    return std::binary_search(links_a.begin(), links_a.end(), b);
}

bool Solve(bool bCheckInputStream = false)
{
    // First input operation
    //
    VertexId n;
    size_t m, k;
    std::cin >> n >> m >> k;

    if (bCheckInputStream && !std::cin)
    {
        return false;
    }

    //StopWatchEx _sw;

    VertexVector2d links(n);
    MapEdgeToVertexSet forbidden;
    // Other input operations and calculations
    //

    for (size_t i = 0; i < m; ++i)
    {
        VertexId x, y;
        std::cin >> x >> y;
        --x; --y;
        links[x].push_back(y);
        links[y].push_back(x);
    }

    for (VertexId i = 0; i < n; i++)
    {
        std::sort(links[i].begin(), links[i].end());
    }

    for (size_t i = 0; i < k; ++i)
    {
        VertexId a, b, c;
        std::cin >> a >> b >> c;
        --a; --b; --c;
        forbidden[TwoPoints(a, b)].insert(c);
    }

    DataFieldVector2d data = CreateVector2d<DataField>(n, n);

    const VertexId startId = 0;
    const VertexId stopId = n-1;

    EdgeList queue;
    // first step
    for(size_t i = 0; i < n; i++)
    {
        data[i][startId].minWay = 0;
        data[i][startId].be = 1;
    }
    for(size_t i = 0; i < links[startId].size(); ++i)
    {
        queue.push_back(Edge(startId, links[startId][i], 0));
    }

    // other steps
    EdgeList::const_iterator pBlockBegin = queue.begin();
    EdgeList::const_iterator pBlockEnd = queue.end();

    bool bStopFound = false;
    EdgeList::const_iterator pStop;

    while (pBlockBegin != pBlockEnd && !bStopFound)
    {
        EdgeList::const_iterator pCurBlockEnd = pBlockEnd;

        for (EdgeList::const_iterator pI = pBlockBegin; pI != pCurBlockEnd && !bStopFound; ++pI)
        {
            const Edge& nextEdge = *pI;

            if (!data[nextEdge.from][nextEdge.to].be)
            {
                data[nextEdge.from][nextEdge.to].be = 1;
                data[nextEdge.from][nextEdge.to].minWay = nextEdge.minWayPrev + 1;

                if (nextEdge.to == stopId)
                {
                    bStopFound = true;
                    pStop = pI;
                }
                else
                {
                    const TwoPoints nextEdgeTP(nextEdge.from, nextEdge.to);
                    for (size_t i = 0; i < links[nextEdge.to].size(); i++)
                    {
                        const VertexId nextNextId = links[nextEdge.to][i];
                        if (!data[nextEdge.to][nextNextId].be)
                        {
                            if (!IsForbidden(forbidden, nextEdgeTP, nextNextId))
                            {
                                queue.push_back(Edge(nextEdge.to, nextNextId, data[nextEdge.from][nextEdge.to].minWay, &nextEdge));
                            }
                        }
                    }
                }
            }
        }

        pBlockBegin = pCurBlockEnd;
        pBlockEnd = queue.end();
    }

    if (bStopFound)
    {
        VertexVector sequence;
        const Edge* pNext = pStop->pPrevEdge;
        sequence.push_back(pStop->to);
        sequence.push_back(pStop->from);

        while (pNext != NULL)
        {
            sequence.push_back(pNext->from);
            pNext = pNext->pPrevEdge;
        }

        std::reverse(sequence.begin(), sequence.end());

        std::cout << sequence.size() - 1 << std::endl;
        for(size_t i = 0; i < sequence.size(); ++i)
        {
            std::cout << sequence[i] + 1 << ' ';
        }
        std::cout << std::endl;
    }
    else
    {
        std::cout << "-1" << std::endl;
    }

    return true;
    // End of all calculations
}

int main()
{
    Prepare();

#if defined(ONLINE_JUDGE)
    Solve();
#else //defined(ONLINE_JUDGE)
    while (Solve(true)) { }
    //Solve();
#endif //defined(ONLINE_JUDGE)
}

// Test-specific stuff

#if !defined(ONLINE_JUDGE)
#endif // !defined(ONLINE_JUDGE)

#if !defined(ONLINE_JUDGE)
#include <windows.h>
#endif //!defined(ONLINE_JUDGE)

struct StopWatchEx::Data
{
#if !defined(ONLINE_JUDGE)
    FILETIME timeStartSystem;
    FILETIME timeStartUser;
#endif //!defined(ONLINE_JUDGE)
};

StopWatchEx::StopWatchEx()
{
#if !defined(ONLINE_JUDGE)
    pData = new Data();
    FILETIME dummy;
    GetProcessTimes(GetCurrentProcess(), &dummy, &dummy, &dummy, &pData->timeStartUser);
    GetSystemTimeAsFileTime(&pData->timeStartSystem);
#endif //!defined(ONLINE_JUDGE)
}

#if !defined(ONLINE_JUDGE)
ULONGLONG FileTimeToU64(const FILETIME& time)
{
    return ((ULONGLONG)time.dwHighDateTime << 32) | time.dwLowDateTime;
}

ULONGLONG GetTimeDiffMs(const FILETIME& first, const FILETIME& second)
{
    return ((FileTimeToU64(first) - FileTimeToU64(second)) + 9999) / 10000;
}
#endif // !defined(ONLINE_JUDGE)

StopWatchEx::~StopWatchEx()
{
#if !defined(ONLINE_JUDGE)
    FILETIME timeCreated;
    FILETIME timeStopUser;
    FILETIME dummy;
    GetProcessTimes(GetCurrentProcess(), &timeCreated, &dummy, &dummy, &timeStopUser);

    FILETIME timeCurrent;
    GetSystemTimeAsFileTime(&timeCurrent);

    std::cout << std::setw(20) << "Total process = " << GetTimeDiffMs(timeCurrent, timeCreated) << " ms" << std::endl;
    std::cout << std::setw(20) << "UserTime diff = " << GetTimeDiffMs(timeStopUser, pData->timeStartUser) << " ms" << std::endl;
    std::cout << std::setw(20) << "SysTime diff = " << GetTimeDiffMs(timeCurrent, pData->timeStartSystem) << " ms" << std::endl;
    std::cout << std::endl;

    delete pData;
#endif //!defined(ONLINE_JUDGE)
}

void Prepare()
{
#if !defined(ONLINE_JUDGE)
    SetProcessAffinityMask(GetCurrentProcess(), 1);
#endif //!defined(ONLINE_JUDGE)
}


#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <vector>
#include <queue>
#include <stack>
#include <deque>
#include <map>
#include <set>
#include <string>
#include <algorithm>
#include <iostream>
#include <complex>
using namespace std;
#define pb push_back
#define mp make_pair
#define point complex<double>
#define tr pair<pair<int, int>, int>
#define pii pair<int, int>
#define xx first
#define yy second

const int maxn=3005, inf=1000000000;
char g[maxn][maxn];
int dis[maxn][maxn], prv[maxn][maxn], n;
queue<pii> qq;
set<tr> st;
vector<int> ans;

void bfs()
{
    int i, j, k;
    for(i=1; i<=n; i++)
        for(j=i+1; j<=n; j++)
            dis[i][j]=dis[j][i]=inf;
    for(k=1; k<=n; k++)
        if (g[1][k])
        {
            dis[1][k]=1;
            qq.push(mp(1, k));
        }
    while(!qq.empty())
    {
        i=qq.front().xx;
        j=qq.front().yy;
        qq.pop();
        for(k=1; k<=n; k++)
            if (g[j][k] && dis[j][k]==inf && st.find(mp(mp(i, j), k))==st.end())
            {
                dis[j][k]=dis[i][j]+1;
                qq.push(mp(j, k));
                prv[j][k]=i;
            }
    }
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
    #endif
    int m, i, j, k, a, b, c, mn, mini;
    cin >> n >> m >>k;
    for(i=0; i<m; i++)
    {
        cin >> a >> b;
        g[a][b]=g[b][a]=1;
    }
    for(i=0; i<k; i++)
    {
        cin >> a >> b >> c;
        st.insert(mp(mp(a, b), c));
    }
    bfs();
    mn=inf;
    for(i=1; i<n; i++)
        if (dis[i][n]<mn)
        {
            mn=dis[i][n];
            mini=i;
        }
    if (mn==inf)
    {
        cout << "-1";
        return 0;
    }
    for(i=mini, j=n; i!=1; )
    {
        ans.pb(j);
        k=prv[i][j];
        j=i;
        i=k;
    }
    ans.pb(j);
    ans.pb(i);
    cout << mn << endl;
    for(i=ans.size()-1; i>=0; i--)
        cout << ans[i] << " ";
}


#include <iostream>
#include <algorithm>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <cstdio>
#include <queue>
#include <map>

using namespace std;

int N , M , K , D[3500][3500] , Par[3500][3500];

map <pair <int , pair<int , int> > , bool> Banned;

vector <int> Graph[3500];

queue <pair <int , int> > Q;

int main()
{
scanf("%d %d %d",&N , &M , &K);
for (int i = 1 ; i <= M ; i ++ )
{
    int L , R ;
    scanf("%d %d",&L , &R);
    Graph[L].push_back(R);
    Graph[R].push_back(L);
};
for (int i = 1 ; i <= K ; i ++ )
{
    int A , B , C;
    scanf("%d %d %d",&A , &B , &C);
    Banned[make_pair(A , make_pair(B , C) )] = true;
};
for (int i = 1 ; i <= N ; i ++ )
    for (int j = 1 ; j <= N ; j ++ )
        D[i][j] = 1 << 30;
D[1][1] = 0;
Q.push(make_pair(1 , 1) );
while ( !Q.empty() )
{
    int v = Q.front().first , par = Q.front().second;
    Q.pop();
    for (int i = 0 ; i < Graph[v].size() ; i ++ )
    {
        int u = Graph[v][i];
        if ( Banned.find(make_pair(par , make_pair(v , u) ) ) != Banned.end() )
            continue;
        if ( D[v][u] > D[par][v] + 1 )
        {
            D[v][u] = D[par][v] + 1;
            Par[v][u] = par;
            Q.push(make_pair(u , v) );
        };
    };
};
int answer = 1 << 30 , cur_par , v = N;
for (int i = 1 ; i < N ; i ++ )
    if ( answer > D[i][N] )
    {
        answer = D[i][N];
        cur_par = i;
    };
if ( answer == 1 << 30 )
{
    printf("-1\n");
    return 0;
};
printf("%d\n",answer);
vector <int> path;
path.push_back(N);
for ( ; Par[cur_par][v] ; )
{
    int u = Par[cur_par][v];
    path.push_back(cur_par);
    v = cur_par;
    cur_par = u;
};
for (int i = path.size() - 1 ; i >= 0 ; i -- )
    printf("%d ",path[i]);
printf("\n");
return 0;
}


#include <iostream>
#include <algorithm>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <cstdio>
#include <queue>
#include <map>

using namespace std;

int N , M , K , D[3500][3500] , Par[3500][3500];

map <pair <int , pair<int , int> > , bool> Banned;

vector <int> Graph[3500];

queue <pair <int , int> > Q;

int main()
{
scanf("%d %d %d",&N , &M , &K);
for (int i = 1 ; i <= M ; i ++ )
{
    int L , R ;
    scanf("%d %d",&L , &R);
    Graph[L].push_back(R);
    Graph[R].push_back(L);
};
for (int i = 1 ; i <= K ; i ++ )
{
    int A , B , C;
    scanf("%d %d %d",&A , &B , &C);
    Banned[make_pair(A , make_pair(B , C) )] = true;
};
for (int i = 1 ; i <= N ; i ++ )
    for (int j = 1 ; j <= N ; j ++ )
        D[i][j] = 1 << 30;
D[1][1] = 0;
Q.push(make_pair(1 , 1) );
while ( !Q.empty() )
{
    int v = Q.front().first , par = Q.front().second;
    Q.pop();
    for (int i = 0 ; i < Graph[v].size() ; i ++ )
    {
        int u = Graph[v][i];
        if ( Banned[make_pair(par , make_pair(v , u) )] )
            continue;
        if ( D[v][u] > D[par][v] + 1 )
        {
            D[v][u] = D[par][v] + 1;
            Par[v][u] = par;
            Q.push(make_pair(u , v) );
        };
    };
};
int answer = 1 << 30 , cur_par , v = N;
for (int i = 1 ; i < N ; i ++ )
    if ( answer > D[i][N] )
    {
        answer = D[i][N];
        cur_par = i;
    };
if ( answer == 1 << 30 )
{
    printf("-1\n");
    return 0;
};
printf("%d\n",answer);
vector <int> path;
path.push_back(N);
for ( ; Par[cur_par][v] ; )
{
    int u = Par[cur_par][v];
    path.push_back(cur_par);
    v = cur_par;
    cur_par = u;
};
for (int i = path.size() - 1 ; i >= 0 ; i -- )
    printf("%d ",path[i]);
printf("\n");
return 0;
}


#include <iostream>
#include <algorithm>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <cstdio>
#include <queue>
#include <map>

using namespace std;

int N , M , K , D[3500][3500] , Par[3500][3500];

map <pair <int , pair<int , int> > , bool> Banned;

vector <int> Graph[3500];

queue <pair <int , int> > Q;

int main()
{
scanf("%d %d %d",&N , &M , &K);
for (int i = 1 ; i <= M ; i ++ )
{
    int L , R ;
    scanf("%d %d",&L , &R);
    Graph[L].push_back(R);
    Graph[R].push_back(L);
};
for (int i = 1 ; i <= K ; i ++ )
{
    int A , B , C;
    scanf("%d %d %d",&A , &B , &C);
    Banned[make_pair(A , make_pair(B , C) )] = true;
};
for (int i = 1 ; i <= N ; i ++ )
    for (int j = 1 ; j <= N ; j ++ )
        D[i][j] = 1 << 30;
D[1][1] = 0;
Q.push(make_pair(1 , 1) );
while ( !Q.empty() )
{
    int v = Q.front().first , par = Q.front().second;
    Q.pop();
    for (int i = 0 ; i < Graph[v].size() ; i ++ )
    {
        int u = Graph[v][i];
        if ( Banned.count(make_pair(par , make_pair(v , u) ) ) != 0 )
            continue;
        if ( D[v][u] > D[par][v] + 1 )
        {
            D[v][u] = D[par][v] + 1;
            Par[v][u] = par;
            Q.push(make_pair(u , v) );
        };
    };
};
int answer = 1 << 30 , cur_par , v = N;
for (int i = 1 ; i < N ; i ++ )
    if ( answer > D[i][N] )
    {
        answer = D[i][N];
        cur_par = i;
    };
if ( answer == 1 << 30 )
{
    printf("-1\n");
    return 0;
};
printf("%d\n",answer);
vector <int> path;
path.push_back(N);
for ( ; Par[cur_par][v] ; )
{
    int u = Par[cur_par][v];
    path.push_back(cur_par);
    v = cur_par;
    cur_par = u;
};
for (int i = path.size() - 1 ; i >= 0 ; i -- )
    printf("%d ",path[i]);
printf("\n");
return 0;
}


#pragma comment (linker, "/stack:640000000")
#include <iostream>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
#include <cassert>
#include <climits>
#include <queue>
#include <ctime>
#include <cmath>
#include <cstdio>
#include <cctype>
using namespace std;

#define forn(i,n) for (int i = 0; i < (int) (n); i++)
#define for1(i,n) for (int i = 1; i <= (int) (n); i++)
#define li long long
#define ld long double
#define pt pair <int, int>
#define x first
#define y second
#define fs first
#define sc second
#define mp make_pair
#define all(v) v.begin(), v.end()
#define pb push_back
#define sz(v) (int)v.size()

const int NMAX = 3000, base = 1000*1000*1000, INF = 1000*1000*1000;
const ld eps = 1e-9, PI = 3.1415926535897932384626433832795;

int main ()
{
    //freopen ("input.txt", "r", stdin);
    //freopen ("output.txt", "w", stdout);

    int n, m, k;
    vector <int> g[NMAX];
    set <pt> bad[NMAX];

    scanf ("%d%d%d", &n, &m, &k);
    forn (i, m)
    {
        int x, y;
        scanf ("%d%d", &x, &y);
        x--, y--;

        g[x].push_back (y);
        g[y].push_back (x);
    }

    forn (i, k)
    {
        int x, y, z;
        scanf ("%d%d%d", &x, &y, &z);
        x--, y--, z--;

        bad[x].insert (mp (y, z));
    }

    int d[NMAX][NMAX], p[NMAX][NMAX];
    queue <pt> q;

    memset (d, -1, sizeof (d));
    memset (p, -1, sizeof (p));
    d[0][0] = 0;
    q.push (mp (0, 0));

    pt fin = mp (-1, -1);

    while (!q.empty())
    {
        pt t = q.front(); q.pop();

        if (t.second == n - 1)
        {
            fin = t;
            break;
        }

        forn (i, g[t.second].size())
        {
            int to = g[t.second][i];

            if (bad[t.first].count (mp (t.second, to)) != 0)
                continue;

            if (d[t.second][to] == -1)
            {
                d[t.second][to] = d[t.first][t.second] + 1;
                p[t.second][to] = t.first;
                q.push (mp (t.second, to));
            }
        }
    }

    if (fin.first == -1)
    {
        cout << -1;
        return 0;
    }

    printf ("%d\n", d[fin.first][fin.second]);

    vector <int> v;

    while (p[fin.x][fin.y] != -1)
    {
        v.pb (fin.y);

        fin = mp (p[fin.x][fin.y], fin.x);
    }

    cout << 1;

    for (int i = v.size() - 1; i >= 0; i--)
        printf (" %d", v[i] + 1);

    return 0;
}


#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>

using namespace std;

typedef long long LL;
typedef vector<int> vint;
typedef vector<vint> vvint;

const int inf = 1000 * 1000 * 1000;

int n, m, k;
vvint D, P, U, G;
queue<int> Q;
map<pair<pair<int, int>, int>, int> M;

int main()
{
	scanf("%d%d%d",&n, &m, &k);
	G.resize(n);
	D.resize(n, vint(n, inf));
	U.resize(n, vint(n, 0));
	P.resize(n, vint(n, 0));
	for(int i = 0; i < m;++i)
	{
		int from, to;
		scanf("%d%d", &from, &to);
		G[from - 1].push_back(to - 1);
		G[to - 1].push_back(from - 1);
	}
	for(int i = 0; i < k; ++i)
	{
		int a, b, c;
		scanf("%d%d%d", &a, &b, &c);
		M[make_pair(make_pair(a - 1, b - 1), c - 1)] = 1;
	}
	U[0][0] = 1;
	D[0][0] = 0;
	Q.push(0);
	Q.push(0);
	bool f = 0;
	while (!Q.empty())
	{
		int from = Q.front();
		Q.pop();
		int now = Q.front();
		Q.pop();
		if (now == n - 1)
		{
			f = 1;
			break;
		}
		for(int i = 0; i < G[now].size(); ++i)
		{
			int to = G[now][i];
			if (!U[now][to] && !M[make_pair(make_pair(from, now), to)])
			{
				U[now][to] = 1;
				D[now][to] = D[from][now] + 1;
				P[now][to] = from;
				Q.push(now);
				Q.push(to);
			}
		}
	}
	int res = inf;
	for(int i = 0; i < n; ++i)
		res = min(res, D[i][n - 1]);
	if (!f)
	{
		printf("-1\n");
		return 0;
	}
	printf("%d\n", res);
	vint ans;
	int from, now = n - 1;
	for(int i = 0; i < n; ++i)
		if (D[i][n - 1] == res)
			from = i;
	ans.push_back(now);
	ans.push_back(from);
	while (1)
	{
		int t = P[from][now];
		ans.push_back(t);
		if (!t)
			break;
		now = from;
		from = t;
	}
	for(int i = ans.size() - 1; i >= 0; --i)
		printf("%d ", ans[i] + 1);
	printf("\n");
	return 0;
}


#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>

using namespace std;

typedef long long LL;
typedef vector<int> vint;
typedef vector<vint> vvint;

const int inf = 1000 * 1000 * 1000;

int n, m, k;
vvint D, P, U, G;
queue<int> Q;
map<pair<pair<int, int>, int>, int> M;

int main()
{
	scanf("%d%d%d",&n, &m, &k);
	G.resize(n);
	D.resize(n, vint(n, inf));
	U.resize(n, vint(n, 0));
	P.resize(n, vint(n, 0));
	for(int i = 0; i < m;++i)
	{
		int from, to;
		scanf("%d%d", &from, &to);
		G[from - 1].push_back(to - 1);
		G[to - 1].push_back(from - 1);
	}
	for(int i = 0; i < k; ++i)
	{
		int a, b, c;
		scanf("%d%d%d", &a, &b, &c);
		M[make_pair(make_pair(a - 1, b - 1), c - 1)] = 1;
	}
	U[0][0] = 1;
	D[0][0] = 0;
	Q.push(0);
	Q.push(0);
	bool f = 0;
	while (!Q.empty())
	{
		int from = Q.front();
		Q.pop();
		int now = Q.front();
		Q.pop();
		if (now == n - 1)
		{
			f = 1;
			break;
		}
		for(int i = 0; i < G[now].size(); ++i)
		{
			int to = G[now][i];
			if (!U[now][to] && !M[make_pair(make_pair(from, now), to)])
			{
				U[now][to] = 1;
				D[now][to] = D[from][now] + 1;
				P[now][to] = from;
				Q.push(now);
				Q.push(to);
			}
		}
	}
	int res = inf;
	for(int i = 0; i < n; ++i)
		res = min(res, D[i][n - 1]);
	if (!f)
	{
		printf("-1\n");
		return 0;
	}
	printf("%d\n", res);
	vint ans;
	int from, now = n - 1;
	for(int i = 0; i < n; ++i)
		if (D[i][n - 1] == res)
			from = i;
	ans.push_back(now);
	while (1)
	{
		int t = P[from][now];
		ans.push_back(from);
		if (!from)
			break;
		now = from;
		from = t;
	}
	for(int i = ans.size() - 1; i >= 0; --i)
		printf("%d ", ans[i] + 1);
	printf("\n");
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/STACK:64000000")
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
#include <cmath>
#include <set>
#include <map>
#include <cassert>
#include <queue>
#include <deque>
#include <stack>
#include <sstream>
#include <cstring>
#include <string>
#include <functional>
#include <numeric>

using namespace std;

#define MP make_pair
#define all(v) (v).begin(), (v).end()

const int INF = ((1 << 31) - 1);
const long long LLINF = (((1LL << 63) - 1LL));
const double eps = 1e-9;
const double PI = 3.14159265358979323846;

typedef long long ll;

int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
    int n;
    cin >> n;
    vector<vector<int> > bad(n * n);
    vector<int> ptr(n*n);
    vector<vector<int> > al(n);
    int m, k;
    cin >> m >> k;
    for (int i = 0 ; i < m; ++i) {
        int a, b;
        scanf("%d%d", &a, &b);
        --a;
        --b;
        al[a].push_back(b);
        al[b].push_back(a);
    }
    for (int i = 0; i < k; ++i) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        --a;
        --b;
        --c;
        bad[a * n + b].push_back(c);
    }
    for (int i = 0; i < n*n; ++i) {
        sort(all(bad[i]));
        if (i < n)
            sort(all(al[i]));
    }
    vector<int> dist(n * n, INF);
    vector<int> prev(n * n, INF);
    dist[0] = 0;
    queue<int> Q;
    Q.push(0);;
    while(!Q.empty()) {
        int v = Q.front();
        Q.pop();
        int p = v % n;
        int pp = v / n;
        if (p == n - 1)
            break;
        for (int i = 0; i < al[p].size(); ++i) {
            int v2 = al[p][i];
            while (ptr[v] < bad[v].size() && bad[v][ptr[v]] < v2) {
                ++ptr[v];
            }
            if (ptr[v] < bad[v].size() && bad[v][ptr[v]] == v2) {
                continue;
            }
            int nv = p * n + v2;
            if (dist[nv] == INF) {
                dist[nv] = dist[v] + 1;
                prev[nv]  = v;
                Q.push(nv);
            }
        }
    }
    int how = -1;
    int res = INF;
    for (int i = 0; i < n; ++i) {
        if (dist[i * n + n - 1] < res) {
            res = dist[i * n + n - 1];
            how = i;
        }
    }
    if (res == INF) {
        cout << -1;
        return 0;
    }
    cout << res << "\n";
    vector<int> path;
    int p = n - 1;
    int pp = how;
    while(p) {
        path.push_back(p);
        int v = prev[pp * n + p];
        pp = v / n;
        p = v % n;
    }
    path.push_back(0);
    reverse(all(path));
    for (int i = 0; i < path.size(); ++i) {
        printf("%d ", path[i ] + 1);
    }
	return 0;
}


#pragma comment(linker, "/STACK:256000000")
#define _CRT_SECURE_NO_WARNINGS

#include <functional>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstring>
#include <bitset>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <set>
#include <map>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const int INF = 1000 * 1000 * 1000;
const double EPS = 1e-9;

#define ALL(v) v.begin(), v.end()
#define SZ(v) (int) v.size()
#define SQR(x) ((x) * (x))
#define MP make_pair

struct Triple {
    int x, y, z;

    Triple(int _x, int _y, int _z) {
        x = _x;
        y = _y;
        z = _z;
    }

    bool operator <(const Triple &o) const {
        return x < o.x || x == o.x && y < o.y || x == o.x && y == o.y && z < o.z;
    }
};

vector<vector<int> > g;

set<Triple> cs;

bool vis[3030][3030];
int dst[3030][3030];
int p[3030][3030];

void addEdge(int u, int v) {
    g[u].push_back(v);
    g[v].push_back(u);
}

int main() {
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
    #endif

    int N, M, K;

    scanf("%d%d%d", &N, &M, &K);

    g.resize(N);

    for (int i = 0; i < M; ++i) {
        int u, v;
        scanf("%d%d", &u, &v);
        addEdge(u - 1, v - 1);
    }

    for (int i = 0; i < K; ++i) {
        int x, y, z;
        scanf("%d%d%d", &x, &y, &z);
        cs.insert(Triple(x - 1, y - 1, z - 1));
    }

    for (int i = 0; i < N; ++i)
        for (int j = 0; j < N; ++j) {
            dst[i][j] = INF;
        }

    queue<pii> q;

    q.push(MP(0, 0));

    vis[0][0] = true;
    dst[0][0] = 0;

    while (!q.empty()) {
        pii cur = q.front();
        q.pop();
        int from = cur.first, now = cur.second;
        for (int i = 0; i < SZ(g[now]); ++i) {
            int to = g[now][i];
            if (!vis[now][to] && cs.find(Triple(from, now, to)) == cs.end()) {
                vis[now][to] = true;
                if (dst[now][to] > dst[from][now] + 1) {
                    dst[now][to] = dst[from][now] + 1;
                    p[now][to] = from;
                }
                q.push(MP(now, to));
            }
        }
    }

    pii c;

    int d = INF;

    for (int i = 0; i < SZ(g[N - 1]); ++i)
        if (dst[g[N - 1][i]][N - 1] < d) {
            d = dst[g[N - 1][i]][N - 1];
            c = MP(g[N - 1][i], N - 1);
        }

    if (d == INF) {
        puts("-1");
    } else {
        printf("%d\n", d);
        vector<int> path;
        while (c.first != 0) {
            path.push_back(c.second);
            c = MP(p[c.first][c.second], c.first);
        }
        path.push_back(c.second);
        path.push_back(c.first);
        reverse(ALL(path));
        for (int i = 0; i < SZ(path); ++i) {
            printf("%d ", path[i] + 1);
        }
    }

    return 0;
}


// I love natalia

#include <iostream>
#include <cstdio>
#include <vector>
#include <set>
#include <queue>
#include <stack>

using namespace std;

vector <int> G[3010];

typedef struct {
    unsigned int len;
    int from;
    int loop;
} T3;

//unsigned int A[3010];
T3 A[3010];

typedef struct {
    int a;
    int b;
    int c;
} T1;

bool operator< (const T1& a, const T1& b) {
    return make_pair(make_pair(a.a, a.b), a.c) < make_pair(make_pair(b.a, b.b), b.c);
}

typedef struct {
    int prev;
    int cur;
    int len;
} T2;

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "rt", stdin);
#endif

    int n, m, k;
    cin >> n >> m >> k;

    for (int i = 0; i < m; i++) {
        int x, y;
        cin >> x >> y;

        G[x].push_back(y);
        G[y].push_back(x);
    }

    set <T1> S;

    for (int i = 0; i < k; i++) {
        T1 tmp;
        cin >> tmp.a >> tmp.b >> tmp.c;

        S.insert(tmp);
    }

    // bfs
    //memset(A, -1, sizeof(A)); //UINT_MAX
    for (int i = 1; i <= n; i++) {
        A[i].len  = UINT_MAX;
        A[i].from = 0;
        A[i].loop = 0;
    }

    queue <T2> Q;

    T2 tmp;
    tmp.prev = 0; tmp.cur = 1; tmp.len = 0;

    T3 tmpt3;
    tmpt3.len = 0; tmpt3.from = 0; tmpt3.loop = 0;

    A[1] = tmpt3;

    Q.push(tmp);

    while (!Q.empty()) {
        int a = Q.front().prev;
        int b = Q.front().cur;

        int l = Q.front().len;

        Q.pop();

        for (int i = 0; i < G[b].size(); i++) {
            int c = G[b][i];

            if (c != a && A[c].len > l+1) {
                T1 tmp;
                tmp.a = a; tmp.b = b; tmp.c = c;

                if (S.find(tmp) == S.end()) {
                    T2 tmp;
                    tmp.prev = b; tmp.cur = c; tmp.len = l+1;
                    A[c].len = l+1;
                    A[c].from = b;
                    A[c].loop = 0;

                    Q.push(tmp);
                }
                else {
                    if (A[c].len > l+3 && G[b].size() > 2)
                        for (int i = 0; i < G[b].size(); i++) {
                            tmp.c = G[b][i];

                            if ( G[b][i] != a && (S.find(tmp) == S.end()) ) {
                                T2 tmp;
                                tmp.prev = b; tmp.cur = c; tmp.len = l+3;
                                A[c].len = l+3;
                                A[c].from = b;
                                A[c].loop = G[b][i];

                                Q.push(tmp);
                            }
                        }

                    //for (int i = 0; i < G[b].size(); i++) {
                    //  tmp.c = G[b][i];

                    //  if ( G[b][i] != a && (S.find(tmp) == S.end()) ) {
                    //      T2 tmp;
                    //      tmp.prev = b; tmp.cur = c; tmp.len = l+3;
                    //      A[c].len = l+3;
                    //      A[c].from = b;
                    //      A[c].loop = G[b][i];

                    //      Q.push(tmp);
                    //  }
                }
            }
        }
    }

    cout << (int)A[n].len << endl;

    if (A[n].len < UINT_MAX) {
        stack <int> res;
        res.push(n);

        int p = n;
        while (p != 1) {
            res.push(A[p].from);

            if (A[p].loop > 0) {
                res.push(A[p].loop);

                if (A[A[p].from].len == A[A[p].loop].len) {
                    p = A[p].loop;

                }
                else {
                    res.push(A[p].from);

                    p = A[p].from;
                }
            }
            else {
                p = A[p].from;
            }
        }

        while (!res.empty()) {
            cout << res.top() << " ";
            res.pop();
        }
    }

    return 0;
}


// I love natalia

#include <iostream>
#include <cstdio>
#include <vector>
#include <set>
#include <queue>
#include <stack>

using namespace std;

vector <int> G[3010];

typedef struct {
    unsigned int len;
    int from;
    int loop;
} T3;

//unsigned int A[3010];
T3 A[3010];

typedef struct {
    int a;
    int b;
    int c;
} T1;

bool operator< (const T1& a, const T1& b) {
    return make_pair(make_pair(a.a, a.b), a.c) < make_pair(make_pair(b.a, b.b), b.c);
}

typedef struct {
    int prev;
    int cur;
    int len;
} T2;

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "rt", stdin);
#endif

    int n, m, k;
    cin >> n >> m >> k;

    for (int i = 0; i < m; i++) {
        int x, y;
        cin >> x >> y;

        G[x].push_back(y);
        G[y].push_back(x);
    }

    set <T1> S;

    for (int i = 0; i < k; i++) {
        T1 tmp;
        cin >> tmp.a >> tmp.b >> tmp.c;

        S.insert(tmp);
    }

    // bfs
    //memset(A, -1, sizeof(A)); //UINT_MAX
    for (int i = 1; i <= n; i++) {
        A[i].len  = UINT_MAX;
        A[i].from = 0;
        A[i].loop = 0;
    }

    queue <T2> Q;

    T2 tmp;
    tmp.prev = 0; tmp.cur = 1; tmp.len = 0;

    T3 tmpt3;
    tmpt3.len = 0; tmpt3.from = 0; tmpt3.loop = 0;

    A[1] = tmpt3;

    Q.push(tmp);

    while (!Q.empty()) {
        int a = Q.front().prev;
        int b = Q.front().cur;

        int l = Q.front().len;

        Q.pop();

        for (int i = 0; i < G[b].size(); i++) {
            int c = G[b][i];

            if (c != a && A[c].len > l+1) {
                T1 tmp;
                tmp.a = a; tmp.b = b; tmp.c = c;

                if (S.find(tmp) == S.end()) {
                    T2 tmp;
                    tmp.prev = b; tmp.cur = c; tmp.len = l+1;
                    A[c].len = l+1;
                    A[c].from = b;
                    A[c].loop = 0;

                    Q.push(tmp);
                }
                else {
                    if (A[c].len > l+3 && G[b].size() > 2)
                        for (int i = 0; i < G[b].size(); i++) {
                            tmp.c = G[b][i];

                            if ( G[b][i] != a && (S.find(tmp) == S.end()) ) {
                                T2 tmp;
                                tmp.prev = b; tmp.cur = c; tmp.len = l+3;
                                A[c].len = l+3;
                                A[c].from = b;
                                A[c].loop = G[b][i];

                                Q.push(tmp);
                            }
                        }

                    //for (int i = 0; i < G[b].size(); i++) {
                    //  tmp.c = G[b][i];

                    //  if ( G[b][i] != a && (S.find(tmp) == S.end()) ) {
                    //      T2 tmp;
                    //      tmp.prev = b; tmp.cur = c; tmp.len = l+3;
                    //      A[c].len = l+3;
                    //      A[c].from = b;
                    //      A[c].loop = G[b][i];

                    //      Q.push(tmp);
                    //  }
                }
            }
        }
    }

    cout << (int)A[n].len << endl;

    if (A[n].len < UINT_MAX) {
        stack <int> res;
        res.push(n);

        int p = n;
        while (p != 1) {
            res.push(A[p].from);

            if (A[p].loop > 0) {
                res.push(A[p].loop);

                T1 tmp;
                tmp.a = A[A[p].loop].from; tmp.b = A[p].loop; tmp.c = A[p].from;
                if (A[A[p].from].len == A[A[p].loop].len && (S.find(tmp) == S.end()) ) {
                    p = A[p].loop;

                }
                else {
                    res.push(A[p].from);

                    p = A[p].from;
                }
            }
            else {
                p = A[p].from;
            }
        }

        while (!res.empty()) {
            cout << res.top() << " ";
            res.pop();
        }
    }

    return 0;
}


// I love natalia

#include <iostream>
#include <cstdio>
#include <vector>
#include <set>
#include <queue>
#include <stack>

using namespace std;

vector <int> G[3010];

typedef struct {
    unsigned int len;
    int from;
    int loop;
} T3;

//unsigned int A[3010];
T3 A[3010];

typedef struct {
    int a;
    int b;
    int c;
} T1;

bool operator< (const T1& a, const T1& b) {
    return make_pair(make_pair(a.a, a.b), a.c) < make_pair(make_pair(b.a, b.b), b.c);
}

typedef struct {
    int prev;
    int cur;
    int len;
} T2;

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "rt", stdin);
#endif

    int n, m, k;
    cin >> n >> m >> k;

    for (int i = 0; i < m; i++) {
        int x, y;
        cin >> x >> y;

        G[x].push_back(y);
        G[y].push_back(x);
    }

    set <T1> S;

    for (int i = 0; i < k; i++) {
        T1 tmp;
        cin >> tmp.a >> tmp.b >> tmp.c;

        S.insert(tmp);
    }

    // bfs
    //memset(A, -1, sizeof(A)); //UINT_MAX
    for (int i = 1; i <= n; i++) {
        A[i].len  = UINT_MAX;
        A[i].from = 0;
        A[i].loop = 0;
    }

    queue <T2> Q;

    T2 tmp;
    tmp.prev = 0; tmp.cur = 1; tmp.len = 0;

    T3 tmpt3;
    tmpt3.len = 0; tmpt3.from = 0; tmpt3.loop = 0;

    A[1] = tmpt3;

    Q.push(tmp);

    while (!Q.empty()) {
        int a = Q.front().prev;
        int b = Q.front().cur;

        int l = Q.front().len;

        Q.pop();

        for (int i = 0; i < G[b].size(); i++) {
            int c = G[b][i];

            if (c != a && A[c].len > l+1) {
                T1 tmp;
                tmp.a = a; tmp.b = b; tmp.c = c;

                if (S.find(tmp) == S.end()) {
                    T2 tmp;
                    tmp.prev = b; tmp.cur = c; tmp.len = l+1;
                    A[c].len = l+1;
                    A[c].from = b;
                    A[c].loop = 0;

                    Q.push(tmp);
                }
                else {
                    if (A[c].len > l+3 && G[b].size() > 2)
                        for (int i = 0; i < G[b].size(); i++) {
                            tmp.c = G[b][i];

                            if ( G[b][i] != a && (S.find(tmp) == S.end()) ) {
                                T2 tmp;
                                tmp.prev = b; tmp.cur = c; tmp.len = l+3;
                                A[c].len = l+3;
                                A[c].from = b;
                                A[c].loop = G[b][i];

                                Q.push(tmp);
                            }
                        }
                }
            }
        }
    }

    cout << (int)A[n].len << endl;

    if (A[n].len < UINT_MAX) {
        stack <int> res;
        res.push(n);

        int p = n;
        while (p != 1) {
            res.push(A[p].from);

            if (A[p].loop > 0) {
                res.push(A[p].loop);
                res.push(A[p].from);
            }

            p = A[p].from;
        }

        while (!res.empty()) {
            cout << res.top() << " ";
            res.pop();
        }
    }

    return 0;
}


// I love natalia

#include <iostream>
#include <cstdio>
#include <vector>
#include <set>
#include <queue>
#include <stack>

using namespace std;

vector <int> G[3010];

typedef struct {
    unsigned int len;
    int from;
    int loop;
} T3;

//unsigned int A[3010];
T3 A[3010];

typedef struct {
    int a;
    int b;
    int c;
} T1;

bool operator< (const T1& a, const T1& b) {
    return make_pair(make_pair(a.a, a.b), a.c) < make_pair(make_pair(b.a, b.b), b.c);
}

typedef struct {
    int prev;
    int cur;
    int len;
} T2;

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "rt", stdin);
#endif

    int n, m, k;
    cin >> n >> m >> k;

    for (int i = 0; i < m; i++) {
        int x, y;
        cin >> x >> y;

        G[x].push_back(y);
        G[y].push_back(x);
    }

    set <T1> S;

    for (int i = 0; i < k; i++) {
        T1 tmp;
        cin >> tmp.a >> tmp.b >> tmp.c;

        S.insert(tmp);
    }

    // bfs
    //memset(A, -1, sizeof(A)); //UINT_MAX
    for (int i = 1; i <= n; i++) {
        A[i].len  = UINT_MAX;
        A[i].from = 0;
        A[i].loop = 0;
    }

    queue <T2> Q;

    T2 tmp;
    tmp.prev = 0; tmp.cur = 1; tmp.len = 0;

    T3 tmpt3;
    tmpt3.len = 0; tmpt3.from = 0; tmpt3.loop = 0;

    A[1] = tmpt3;

    Q.push(tmp);

    while (!Q.empty()) {
        int a = Q.front().prev;
        int b = Q.front().cur;

        int l = Q.front().len;

        Q.pop();

        for (int i = 0; i < G[b].size(); i++) {
            int c = G[b][i];

            if (c != a && A[c].len > l+1) {
                T1 tmp;
                tmp.a = a; tmp.b = b; tmp.c = c;

                if (S.find(tmp) == S.end()) {
                    T2 tmp;
                    tmp.prev = b; tmp.cur = c; tmp.len = l+1;
                    A[c].len = l+1;
                    A[c].from = b;
                    A[c].loop = 0;

                    Q.push(tmp);
                }
                else {
                    if (A[c].len > l+3 && G[b].size() > 2)
                        for (int i = 0; i < G[b].size(); i++) {
                            tmp.c = G[b][i];

                            if ( G[b][i] != a && (S.find(tmp) == S.end()) ) {
                                T2 tmp;
                                tmp.prev = b; tmp.cur = c; tmp.len = l+3;
                                A[c].len = l+3;
                                A[c].from = b;
                                A[c].loop = G[b][i];

                                Q.push(tmp);
                            }
                        }

                    //for (int i = 0; i < G[b].size(); i++) {
                    //  tmp.c = G[b][i];

                    //  if ( G[b][i] != a && (S.find(tmp) == S.end()) ) {
                    //      T2 tmp;
                    //      tmp.prev = b; tmp.cur = c; tmp.len = l+3;
                    //      A[c].len = l+3;
                    //      A[c].from = b;
                    //      A[c].loop = G[b][i];

                    //      Q.push(tmp);
                    //  }
                }
            }
        }
    }

    //cout << (int)A[n].len << endl;

    if (A[n].len < UINT_MAX) {
        stack <int> res;
        res.push(n);

        int p = n;
        while (p != 1) {
            res.push(A[p].from);

            if (A[p].loop > 0) {
                res.push(A[p].loop);

                T1 tmp;
                tmp.a = A[A[p].loop].from; tmp.b = A[p].loop; tmp.c = A[p].from;
                if (A[A[p].from].len == A[A[p].loop].len && (S.find(tmp) == S.end()) ) {
                    p = A[p].loop;
                    A[n].len--;
                }
                else {
                    res.push(A[p].from);

                    p = A[p].from;
                }
            }
            else {
                p = A[p].from;
            }
        }

        cout << (int)A[n].len << endl;
        while (!res.empty()) {
            cout << res.top() << " ";
            res.pop();
        }
    }
    else
        cout << "-1";

    return 0;
}


/*
 * Author: iSea
 * Created Time:  2011/3/24 19:20:25
 * File Name: E.cpp
 */
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>

using namespace std;

#define PB push_back
#define PII pair<int, int>
#define SZ(x) ((int)((x).size()))
#define OUT(x) printf(#x" %d\n", x)
#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)

const int maxn = 3000 + 10;
const int inf = (-1u) >> 1;

set<long long> fb;
vector<int> g[maxn];
int n, m, k;
int pre[maxn][maxn];
bool v[maxn][maxn];

long long hash(int x, int y, int z) {
    return (long long)x * 9000000 + y * 3000 + z;
}

bool fbed(int x, int y, int z) {
    return fb.find(hash(x, y, z)) != fb.end();
}

void init() {
    FOR(i,1,n) {
        g[i].clear();
    }
    REP(i,m) {
        int a, b;
        scanf ("%d%d", &a, &b);
        g[a].PB(b), g[b].PB(a);
    }
    fb.clear();
    REP(i,k) {
        int a, b, c;
        scanf ("%d%d%d", &a, &b, &c);
        fb.insert (hash(a, b, c));
    }
}

void output(int x, int y) {
    vector<int> ans;
    ans.PB(y);
    while (x) {
        ans.PB(x);
        int t = pre[x][y];
        y = x, x = t;
    }
    printf ("%d\n", SZ(ans) - 1);
    reverse(ans.begin(), ans.end());
    REP(i,SZ(ans)) {
        printf ("%d%c", ans[i], i == SZ(ans)-1? '\n' : ' ');
    }
}

void solve() {
    queue<int> q;
    q.push(0), q.push(1);
    memset (v, 0, sizeof(v));
    v[0][1] = true;
    while (!q.empty()) {
        int x = q.front(); q.pop();
        int y = q.front(); q.pop();
        if (y == n) {
            output(x, y);
            return ;
        }
        for (vector<int>::iterator it = g[y].begin(); it != g[y].end(); ++it) {
            if (!fbed(x, y, *it) && !v[y][*it]) {
                v[y][*it] = true;
                pre[y][*it] = x;
                q.push(y), q.push(*it);
            }
        }
    }
    puts ("-1");
}

int main() {
    while (scanf ("%d%d%d", &n, &m, &k) != EOF) {
        init();
        solve();
    }
    return 0;
}


#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <ctime>
#include <cmath>
#include <memory>
#include <cstring>
#include <utility>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <string>
using namespace std;

typedef long long int LL;
typedef long double LD;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<bool> VB;
typedef vector<VB> VVB;
typedef vector<string> VS;
typedef set<int> SI;
typedef map<int,int> MII;
typedef pair<int,int> II;
typedef vector<II> VII;
typedef vector<VII> VVII;
typedef vector<LL> VL;
typedef vector<VL> VLL;
typedef set<LL> SL;
typedef map<LL,LL> MLL;
typedef pair<LL,LL> LLL;
typedef vector<LD> VD;
typedef vector<VD> VVD;

#define F first
#define S second
#define MP make_pair

template<typename T>
inline T sqr(const T &a){return a*a;}

template<typename T>
inline int nread(vector<T> &a)
{
	int n;
	cin >> n;
	a.clear();
	a.resize(n);
	for (int i=0;i<n;i++) cin >> a[i];
	return n;
}

template<typename T>
inline void nwread(int n, vector<T> &a)
{
	a.clear();
	a.resize(n);
	for (int i=0;i<n;i++) cin >> a[i];
}

#define TASKNAME "a"

const int N=3001;
int gr[N][N],cg[N];
int res[N*N];
pair<int,int> que[N*N];

int main () {
//	freopen(TASKNAME".in","r",stdin);
//	freopen(TASKNAME".out","w",stdout);
	int n,m,k;
	cin >> n >> m >> k;
	for (int i=0;i<n;i++)
		cg[i]=0;
	for (int i=0;i<m;i++) {
		int x,y;
		scanf("%d%d",&x,&y);
		x--;y--;
		gr[x][cg[x]++]=y;
		gr[y][cg[y]++]=x;
	}
	set<pair<II,int> > zapr;
	for (int i=0;i<k;i++) {
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		x--;y--;z--;
		zapr.insert(MP(MP(x,y),z));
	}
	map<II,int> path;
	int qi=0,qj=1;
	que[0]=MP(-1,0);
	while (qi<qj) {
		II tek=que[qi++];
		int pv=tek.F,tv=tek.S;
		VI nreb;
		for (int i=0;i<cg[tv];) {
			int fv=gr[tv][i];
			if (zapr.count(MP(tek,fv)))
				i++;
			else {
				que[qj++]=MP(tv,fv);
				path[MP(tv,fv)]=pv;
				if (fv==n-1) {
					int lr=2;
					res[0]=fv;
					res[1]=tv;
					while (tv!=0) {
						pv=path[MP(tv,fv)];
						res[lr++]=pv;
						fv=tv;
						tv=pv;
					}
					reverse(res,res+lr);
					cout << lr-1 << endl;
					for (int i=0;i<lr;i++) printf("%d ",res[i]+1);
					return 0;
				}
				if (cg[tv]) gr[tv][i]=gr[tv][cg[tv]-1];
				cg[tv]--;
			}
		}
	}
	cout << -1;
}


#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <ctime>
#include <cmath>
#include <memory>
#include <cstring>
#include <utility>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <string>
using namespace std;

typedef long long int LL;
typedef long double LD;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<bool> VB;
typedef vector<VB> VVB;
typedef vector<string> VS;
typedef set<int> SI;
typedef map<int,int> MII;
typedef pair<int,int> II;
typedef vector<II> VII;
typedef vector<VII> VVII;
typedef vector<LL> VL;
typedef vector<VL> VLL;
typedef set<LL> SL;
typedef map<LL,LL> MLL;
typedef pair<LL,LL> LLL;
typedef vector<LD> VD;
typedef vector<VD> VVD;

#define F first
#define S second
#define MP make_pair

template<typename T>
inline T sqr(const T &a){return a*a;}

template<typename T>
inline int nread(vector<T> &a)
{
    int n;
    cin >> n;
    a.clear();
    a.resize(n);
    for (int i=0;i<n;i++) cin >> a[i];
    return n;
}

template<typename T>
inline void nwread(int n, vector<T> &a)
{
    a.clear();
    a.resize(n);
    for (int i=0;i<n;i++) cin >> a[i];
}

#define TASKNAME "a"

int main () {
//  freopen(TASKNAME".in","r",stdin);
//  freopen(TASKNAME".out","w",stdout);
    int n,m,k;
    cin >> n >> m >> k;
    VVI gr(n);
    for (int i=0;i<m;i++) {
        int x,y;
        scanf("%d%d",&x,&y);
        x--;y--;
        gr[x].push_back(y);
        gr[y].push_back(x);
    }
    set<pair<II,int> > zapr;
    for (int i=0;i<k;i++) {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        x--;y--;z--;
        zapr.insert(MP(MP(x,y),z));
    }
    vector<II> que;
    map<II,int> path;
    int qi=0;
    que.push_back(MP(-1,0));
    while (qi<que.size()) {
        II tek=que[qi++];
        int pv=tek.F,tv=tek.S;
        VI nreb;
        for (int i=0;i<gr[tv].size();i++) {
            int fv=gr[tv][i];
            if (zapr.count(MP(tek,fv)))
                nreb.push_back(fv);
            else {
                que.push_back(MP(tv,fv));
                path[MP(tv,fv)]=pv;
                if (fv==n-1) {
                    VI res;
                    res.push_back(fv);
                    res.push_back(tv);
                    while (tv!=0) {
                        pv=path[MP(tv,fv)];
                        res.push_back(pv);
                        fv=tv;
                        tv=pv;
                    }
                    reverse(res.begin(),res.end());
                    cout << res.size()-1 << endl;
                    for (int i=0;i<res.size();i++) cout << res[i]+1 << ' ';
                    return 0;
                }
            }
        }
        gr[tv]=nreb;
    }
    cout << -1;
}


#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <ctime>
#include <cmath>
#include <memory>
#include <cstring>
#include <utility>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <string>
using namespace std;

typedef long long int LL;
typedef long double LD;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<bool> VB;
typedef vector<VB> VVB;
typedef vector<string> VS;
typedef set<int> SI;
typedef map<int,int> MII;
typedef pair<int,int> II;
typedef vector<II> VII;
typedef vector<VII> VVII;
typedef vector<LL> VL;
typedef vector<VL> VLL;
typedef set<LL> SL;
typedef map<LL,LL> MLL;
typedef pair<LL,LL> LLL;
typedef vector<LD> VD;
typedef vector<VD> VVD;

#define F first
#define S second
#define MP make_pair

template<typename T>
inline T sqr(const T &a){return a*a;}

template<typename T>
inline int nread(vector<T> &a)
{
	int n;
	cin >> n;
	a.clear();
	a.resize(n);
	for (int i=0;i<n;i++) cin >> a[i];
	return n;
}

template<typename T>
inline void nwread(int n, vector<T> &a)
{
	a.clear();
	a.resize(n);
	for (int i=0;i<n;i++) cin >> a[i];
}

#define TASKNAME "a"

const int N=3001;
int gr[N][N],cg[N];
int res[N*N];
pair<int,int> que[N*N];

int main () {
//	freopen(TASKNAME".in","r",stdin);
//	freopen(TASKNAME".out","w",stdout);
	int n,m,k;
	cin >> n >> m >> k;
	VVI gr(n);
	for (int i=0;i<m;i++) {
		int x,y;
		scanf("%d%d",&x,&y);
		x--;y--;
		gr[x][cg[x]++]=y;
		gr[y][cg[y]++]=x;
	}
	set<pair<II,int> > zapr;
	for (int i=0;i<k;i++) {
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		x--;y--;z--;
		zapr.insert(MP(MP(x,y),z));
	}
	vector<II> que;
	map<II,int> path;
	int qi=0,qj=1;
	que[0]=MP(-1,0);
	while (qi<qj) {
		II tek=que[qi++];
		int pv=tek.F,tv=tek.S;
		VI nreb;
		for (int i=0;i<cg[tv];) {
			int fv=gr[tv][i];
			if (zapr.count(MP(tek,fv)))
				i++;
			else {
				que[qj++]=MP(tv,fv);
				path[MP(tv,fv)]=pv;
				if (fv==n-1) {
					int lr=2;
					res[0]=fv;
					res[1]=tv;
					while (tv!=0) {
						pv=path[MP(tv,fv)];
						res[lr++]=pv;
						fv=tv;
						tv=pv;
					}
					reverse(res,res+lr);
					cout << lr-1 << endl;
					for (int i=0;i<lr;i++) printf("%d",res[i]+1);
					return 0;
				}
				if (cg[tv]) gr[tv][i]=gr[tv][cg[tv]-1];
				cg[tv]--;
			}
		}
	}
	cout << -1;
}


#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <ctime>
#include <cmath>
#include <memory>
#include <cstring>
#include <utility>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <string>
using namespace std;

typedef long long int LL;
typedef long double LD;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<bool> VB;
typedef vector<VB> VVB;
typedef vector<string> VS;
typedef set<int> SI;
typedef map<int,int> MII;
typedef pair<int,int> II;
typedef vector<II> VII;
typedef vector<VII> VVII;
typedef vector<LL> VL;
typedef vector<VL> VLL;
typedef set<LL> SL;
typedef map<LL,LL> MLL;
typedef pair<LL,LL> LLL;
typedef vector<LD> VD;
typedef vector<VD> VVD;

#define F first
#define S second
#define MP make_pair

template<typename T>
inline T sqr(const T &a){return a*a;}

template<typename T>
inline int nread(vector<T> &a)
{
	int n;
	cin >> n;
	a.clear();
	a.resize(n);
	for (int i=0;i<n;i++) cin >> a[i];
	return n;
}

template<typename T>
inline void nwread(int n, vector<T> &a)
{
	a.clear();
	a.resize(n);
	for (int i=0;i<n;i++) cin >> a[i];
}

#define TASKNAME "a"

const int N=3001;
int gr[N][N],cg[N];
int res[N*N];
pair<int,int> que[N*N];

int main () {
//	freopen(TASKNAME".in","r",stdin);
//	freopen(TASKNAME".out","w",stdout);
	int n,m,k;
	cin >> n >> m >> k;
	for (int i=0;i<m;i++) {
		int x,y;
		scanf("%d%d",&x,&y);
		x--;y--;
		gr[x][cg[x]++]=y;
		gr[y][cg[y]++]=x;
	}
	set<pair<II,int> > zapr;
	for (int i=0;i<k;i++) {
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		x--;y--;z--;
		zapr.insert(MP(MP(x,y),z));
	}
	vector<II> que;
	map<II,int> path;
	int qi=0,qj=1;
	que[0]=MP(-1,0);
	while (qi<qj) {
		II tek=que[qi++];
		int pv=tek.F,tv=tek.S;
		VI nreb;
		for (int i=0;i<cg[tv];) {
			int fv=gr[tv][i];
			if (zapr.count(MP(tek,fv)))
				i++;
			else {
				que[qj++]=MP(tv,fv);
				path[MP(tv,fv)]=pv;
				if (fv==n-1) {
					int lr=2;
					res[0]=fv;
					res[1]=tv;
					while (tv!=0) {
						pv=path[MP(tv,fv)];
						res[lr++]=pv;
						fv=tv;
						tv=pv;
					}
					reverse(res,res+lr);
					cout << lr-1 << endl;
					for (int i=0;i<lr;i++) printf("%d",res[i]+1);
					return 0;
				}
				if (cg[tv]) gr[tv][i]=gr[tv][cg[tv]-1];
				cg[tv]--;
			}
		}
	}
	cout << -1;
}