poj1041John's trip(欧拉回路+输出路径)

->题目请戳这里<-

题目大意:一个小镇有m条街,n个交叉口,每条街上有john的一个朋友,现在john要拜访每个朋友1次,输出字典序最小的访问街道编号。起点是输入第一组数据最小的端点。

题目分析:典型的欧拉回路问题。先判断图是连通的并且所有点度数为偶数,因为这题是无向图,建图的时候每条边正反建一次。由于要字典序最小,所以要先dfs编号较小的街道,所以建图的时候稍微注意一下,我是先把所有的街道排序,先建编号大的边,保证dfs先遍历编号小的街道,从而答案保证字典序最小。详情请见代码:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 20005;
struct node
{
    int from,to,id,next;
    bool vis;
}edge[N];
int flag[N];
struct nd
{
    int a,b,c;
}lcm[N];
int num;
int x,y;
int set[50];
int degree[50];
int start,ind;
int ans[N],top;
int head[50];

int cmp(struct nd a,struct nd b)
{
    if(a.a != b.a)
        return a.a < b.a;
    else
        return a.c > b.c;
}

void init()
{
    int i;
    for(i = 1;i < 50;i ++)
    {
        head[i] = -1;
        set[i] = i;
        degree[i] = 0;
    }
    memset(flag,0,sizeof(flag));
    num = top = 0;
}

int find(int a)
{
    int root = a;
    while(root != set[root])
        root = set[root];
    int parent = set[a];
    while(parent != root)
    {
        set[a] = root;
        a = parent;
        parent = set[a];
    }
    return root;
}

void join(int a,int b)
{
    int root_a = find(a);
    int root_b = find(b);
    set[root_b] = root_a;
}

int isok()
{
    int i;
    int cnt = 0;
    //for(i = 1;i < 50;i ++)
    //    printf("%d ",degree[i]);
    //printf("\n");
    for(i = 1;i < 50;i ++)
    {
        if(set[i] == i && degree[i])
            cnt ++;
        if(cnt > 1)
            return 0;
        if(degree[i] & 1)
            return 0;
    }
    return 1;
}

void build(int s,int e,int idx)
{
    edge[num].from = s;
    edge[num].to = e;
    edge[num].id = idx;
    edge[num].vis = 0;
    edge[num].next = head[s];
    head[s] = num ++;
    flag[idx] = 1;
}

void dfs(int u)
{
    int i;
    for(i = head[u];i != -1;i = edge[i].next)
    {
        if(flag[edge[i].id])
        {
            flag[edge[i].id] = 0;
            dfs(edge[i].to);
            ans[top ++]  = edge[i].id;
        }
    }
}

int main()
{
    int i;
    int t = 0;
    while(scanf("%d%d",&x,&y),(x + y))
    {
        init();
        scanf("%d",&ind);
        lcm[0].a = x;
        lcm[0].b = y;
        lcm[0].c = ind;
        lcm[1].a = y;
        lcm[1].b = x;
        lcm[1].c = ind;
        t = 2;
        start = x > y?y:x;
        //build(x,y,ind);
        degree[x] ++;
        degree[y] ++;
        join(x,y);
        while(scanf("%d%d",&x,&y),(x + y))
        {
            scanf("%d",&ind);
            //build(x,y,ind);
            degree[x] ++;
            degree[y] ++;
            join(x,y);
            lcm[t].a = x;
            lcm[t].b = y;
            lcm[t ++].c = ind;
            lcm[t].a = y;
            lcm[t].b = x;
            lcm[t ++].c = ind;
        }
        sort(lcm,lcm + t,cmp);
        for(i = 0;i < t;i ++)
        {
            build(lcm[i].a,lcm[i].b,lcm[i].c);
            //printf("%d  %d  %d\n",lcm[i].a,lcm[i].b,lcm[i].c);
        }
        if(isok())
        {
            dfs(start);
            //printf("%d\n",top);
            for(i = top - 1;i > 0;i --)
                printf("%d ",ans[i]);
            printf("%d\n",ans[i]);
        }
        else
            printf("Round trip does not exist.\n");
    }
    return 0;
}
//372K	63MS


你可能感兴趣的:(图论)