John's trip

题目链接

  • 题意:
    输入a、b、c,表示点a和点b之间有一条边,边序号为c,现在让从第一次输入的两个点中较小的点(这里题意是个坑),走过所有的边后必须回到起点,输出最小路径
  • 关键:
    欧拉回路+输出路径(边序号)

const int MAXN = 2100;
const int MAXV = 2000;
const int MAXE = 2020 * 2;

struct Edge
{
    int from, to, id;
};

struct UnDirect_Euler
{
    int n, m;
    int deg[MAXV];
    bool vis[MAXE];
    vector<int> G[MAXV];
    vector<Edge> edges;
    stack<int> sk;
    vector<int> ans;

    void init(int n)
    {
        this->n = n;
        edges.clear();
        REP(i, n)
        {
            deg[i] = 0;
            G[i].clear();
        }
    }

    void addEdge(int a, int b, int id)
    {
        edges.push_back((Edge) { a, b, id });
        edges.push_back((Edge) { b, a, id });
        m = edges.size();
        G[a].push_back(m - 2);
        G[b].push_back(m - 1);
        deg[a]++;
        deg[b]++;
    }

    void dfs(int u, int ind)
    {
        REP(i, G[u].size())
        {
            int x = G[u][i];
            Edge& e = edges[x];
            if (!vis[x])
            {
                vis[x] = vis[x ^ 1] = true;
                dfs(e.to, x);
            }
        }
        if (ind >= 0)
            sk.push(ind);
    }


    //返回1:欧拉回路  返回2:欧拉路经
    int solve(int s)
    {
        ans.clear();
        int cnt = 0;
        REP(i, n)
        {
            if (deg[i] == 1)
            {
                if (++cnt > 2) return 0;
                s = i;
            }
            else if (deg[i] % 2 != 0) return 0;
        }
        while (!sk.empty()) sk.pop();
        REP(i, m) vis[i] = false;
        dfs(s, -1);
        REP(i, m) if (!vis[i]) return 0;
        while (!sk.empty())
        {
            ans.push_back(sk.top());
            sk.pop();
        }
        return cnt != 0 ? 1 : 2;
    }
} graph;

struct Node
{
    int a, b, c;
    int operator< (const Node& rhs) const
    {
        return c < rhs.c;
    }
} ipt[MAXN];

int read()
{
    graph.init(MAXV);
    int n;
    for (n = 0;;n++)
    {
        RII(ipt[n].a, ipt[n].b);
        if (ipt[n].a == 0)
            break;
        RI(ipt[n].c);
    }
    sort(ipt, ipt + n);
    REP(i, n)
        graph.addEdge(ipt[i].a, ipt[i].b, ipt[i].c);
    return n;
}

int main()
{
//    freopen("in.txt", "r", stdin);
    while (read())
    {
        int start = min(ipt[0].a, ipt[0].b);
        if (graph.solve(start))
        {
            vector<int>& ans = graph.ans;
            REP(i, ans.size())
            {
                printf("%d%c", graph.edges[ans[i]].id, i == (int)ans.size() - 1 ? '\n' : ' ');
            }
        }
        else
        {
            puts("Round trip does not exist.");
        }
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值