zoukankan      html  css  js  c++  java
  • POJ1041 John's trip 【字典序输出欧拉回路】

    题目链接:http://poj.org/problem?id=1041

    题目大意:给出一个连通图,判断是否存在欧拉回路,若存在输出一条字典序最小的路径。

    我的想法:

    1.一开始我是用结构体记录边的起点终点以及边的序号,然后将序号按照从小到大排序。再用链式前向星来存以及排好序的边,然后dfs从小到大遍历。但是错了,原因是链式前向星遍历边是反向遍历的,并且并没有将边的序号一一对应上。

    正确思路:

    1.首先要明白欧拉回路存在的条件。一.连通图(可以用并查集或者tarjan来判断是否连通)。二.无向图每个点的度为偶数,有向图每个点的入度等于出度。所以在判断欧拉回路之前要先判连通以及度。

    2.这道题的关键在于数据结构的选择,我用结构体+链式前向星就不行。仔细思考输出边序号的字典序最小,那我们就可以用 G[][]二维数组来表示,G[A][B] = C表示A点通过B边与C相连。这样就可以在dfs中从小到大for一遍B来保证优先选择序号小的边。

    3.dfs中利用栈S,在回溯的过程中将路径压入栈中。若此时路径不符合,则代表此次回溯经过的路径应该是在其他路径后面经过的,正好符合栈的输出特点。例如:1-2-3-4-5-6路径回溯时入栈顺序为6-5-4-3-2-1,最后出栈就为1-2-3-4-5-6.正确。

    代码里有注释

    代码:

    注意:因为题目已经说明了保证给出的图是一个连通图,所以这里没有判连通。

    注意:数据有问题,数组要开大点,否则会WA

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 #include<stack>
     5 #define mem(a, b) memset(a, b, sizeof(a))
     6 using namespace std;
     7 
     8 int a, b, c, flag;
     9 int du[2000], vis[5000];
    10 int G[2000][5000]; //关键数组,G[a][b] = c表示a点通过b边与c相连 
    11 int maxm, maxn;
    12 stack<int>S;
    13 
    14 void init()
    15 {
    16     mem(du, 0);
    17     mem(G, 0);
    18     mem(vis, 0);
    19     maxm = -1;
    20     flag = 1;
    21     while(!S.empty())
    22         S.pop();
    23 }
    24 
    25 void dfs(int now)
    26 {
    27     for(int i = 1; i <= maxm; i ++)  //每次dfs都从小的边开始,保证字典序 
    28     {
    29         if(vis[i] || G[now][i] == 0)//若没有边或者已经走过了 
    30             continue;
    31         vis[i] = 1;
    32         dfs(G[now][i]);
    33         S.push(i);//回溯过程中将边入栈,最后倒序输出,若一次走不完,那么回溯完找其他路径,这些路径会被压到栈下面,也表示后面再走 
    34     }
    35 }
    36 
    37 int main()
    38 {
    39     while(scanf("%d%d", &a, &b) != EOF)
    40     {
    41         if(a == 0 && b == 0)
    42             break;
    43         init();
    44         scanf("%d", &c);
    45         du[a] ++, du[b] ++;//度数 
    46         G[a][c] = b, G[b][c] = a;
    47         maxm = max(maxm, c);//边数 
    48         maxn = max(a, b);//点数 
    49         while(1)
    50         {
    51             scanf("%d%d", &a, &b);
    52             if(a == 0 && b == 0)
    53                 break;
    54             scanf("%d", &c);
    55             du[a] ++, du[b] ++;
    56             G[a][c] = b, G[b][c] = a;
    57             maxm = max(maxm, c);
    58             maxn = max(maxn, max(a, b));
    59         }
    60         for(int i = 1; i <= maxn; i ++)
    61             if(du[i] % 2)
    62             {
    63                 flag = 0;
    64                 break;
    65             }
    66         if(!flag)
    67         {
    68             printf("Round trip does not exist.
    ");
    69             continue;
    70         }
    71         dfs(1);
    72         printf("%d", S.top());
    73         S.pop();
    74         while(!S.empty())
    75         {
    76              printf(" %d", S.top());
    77              S.pop();
    78         }
    79         printf("
    ");
    80     }
    81     return 0;
    82 }
    POJ1041
  • 相关阅读:
    设计模式之里氏替换原则
    设计模式之依赖倒转原则
    设计模式之接口分离原则
    spring 集成 kafka producer(KafkaTemplate)
    jmeter 分布式
    ant+Jenkins+jmeter
    pycharm+git+github项目上传
    Python_pip下载不下来源解决方案
    linux_python3环境搭建
    Jenkins+Git+Github+Python自动化化接口项目例子
  • 原文地址:https://www.cnblogs.com/yuanweidao/p/10928372.html
Copyright © 2011-2022 走看看