poj 1041 John's trip

欧拉回路

题意:给一个有向图,判断是否是欧拉回路,并且输出路径, 要求字典序最小。其中输出时这个给的,x y z,x和y是点的编号(点数最多44),z是边的编号(这边是有编号的,边数最大1995),其中输出路径不是输出点而是输出边的编号,所以字典序最小是指边的字典序最小。每组数据以0 0 结束。其中每组数组的第一行,两个点x,y,选较小的那个作为起点

这题,图是保证连通的,所以不需要判断连通,所以判断是不是欧拉图,只需要看每个点的度是否都为偶数,不是的话则不存在欧拉回路,是的话就存在欧拉回路

输出字典序最小的路径,环一个建图方法即可

e[k][0] , e[k][1]表示第k条边的两个顶点

我们用递归的方式去输出路径,从起点开始,然后枚举边,从编号最小的边开始枚举,这样就能保证字典序最小

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
using namespace std;
#define N 50
#define M 2010

int node,edge,sp,Max;
int e[M][2],de[M];
bool used[M];
stack<int>sta;

void dfs(int u)
{
    for(int k=1; k<=edge; k++)
        if(!used[k])
        {
            int v;
            if(e[k][0] == u) v = e[k][1];
            else if(e[k][1] == u) v = e[k][0];
            else continue;
            used[k] = true;
            dfs(v);
            sta.push(k);
        }
}

void solve()
{
    while(!sta.empty()) sta.pop();
    memset(used,false,sizeof(used));
    dfs(sp);
    bool first = true;
    while(!sta.empty())
    {
        if(!first) cout << " ";
        cout << sta.top();
        first = false;
        sta.pop();
    }
    cout << endl;
}

int main()
{
    int u,v,m;
    while(cin >> u >> v)
    {
        if(u == 0 && v == 0) break;
        memset(de,0,sizeof(de));
        sp = min(u,v); Max = max(u,v);
        cin >> m;
        e[m][0] = u;  e[m][1] = v;
        de[u]++;  de[v]++;
        edge = 1;
        while(cin >> u >> v)
        {
            if(u == 0 && v == 0) break;
            Max = max(Max,u); Max = max(Max,v);
            cin >> m;
            e[m][0] = u; e[m][1] = v;
            de[u]++; de[v]++;
            edge++;
        }
        int ok = 1;
        for(int i=1; i<=Max; i++) 
            if(de[i] & 1)
            { ok = 0; break;}
        if(!ok)
        {
            cout << "Round trip does not exist." << endl;
            continue;
        }
        solve();
    }
    return 0;
}

 

posted @ 2013-06-07 18:20  Titanium  阅读(266)  评论(0编辑  收藏  举报