【洛谷】P2731 骑马修栅栏

题目地址:

https://www.luogu.com.cn/problem/P2731

题目背景:
Farmer John每年有很多栅栏要修理。他总是骑着马穿过每一个栅栏并修复它破损的地方。

题目描述:
John是一个与其他农民一样懒的人。他讨厌骑马,因此从来不两次经过一个栅栏。John的农场上一共有 m m m个栅栏,每一个栅栏连接两个顶点,顶点用 1 1 1 500 500 500标号(虽然有的农场并没有那么多个顶点)。一个顶点上至少连接 1 1 1个栅栏,没有上限。两顶点间可能有多个栅栏。所有栅栏都是连通的(也就是你可以从任意一个栅栏到达另外的所有栅栏)。John能从任何一个顶点(即两个栅栏的交点)开始骑马,在任意一个顶点结束。你需要求出输出骑马的路径(用路上依次经过的顶点号码表示),使每个栅栏都恰好被经过一次。如果存在多组可行的解,按照如下方式进行输出:如果把输出的路径看成是一个 500 500 500进制的数,那么当存在多组解的情况下,输出 500 500 500进制表示法中最小的一个 (也就是输出第一位较小的,如果还有多组解,输出第二位较小的,以此类推)。输入数据保证至少有一个解。

输入格式:
第一行一个整数 m m m,表示栅栏的数目。从第二行到第 m + 1 m+1 m+1行,每行两个整数 u , v u,v u,v,表示有一条栅栏连接 u , v u,v u,v两个点。

输出格式:
m + 1 m+1 m+1行,每行一个整数,依次表示路径经过的顶点号。注意数据可能有多组解,但是只有上面题目要求的那一组解是认为正确的。数据保证至少有一组可行解。

数据范围:
对于 100 % 100\% 100%的数据, 1 ≤ m ≤ 1024 , 1 ≤ u , v ≤ 500 1≤m≤1024,1≤u,v≤500 1m1024,1u,v500

欧拉路径问题。先判断是否存在欧拉路径(如果是欧拉回路,则每个点度数都为偶数,从 1 1 1号点出发;否则找到第 1 1 1个度数为奇数的点,该点即为起点),然后DFS一遍即可。代码如下:

#include <iostream>
using namespace std;

const int N = 510, M = 1024 << 1;
int n, m;
int g[N][N], d[N];
int res[(M >> 1) + 10], cnt;

void dfs(int u) {
  for (int i = 1; i <= n; i++)
    if (g[u][i]) {
      g[u][i]--;
      g[i][u]--;
      dfs(i);
    }

  res[cnt++] = u;
}

int main() {
  scanf("%d", &m);
  while (m--) {
    int a, b;
    scanf("%d%d", &a, &b);
    g[a][b]++;
    g[b][a]++;
    d[b]++;
    d[a]++;
    n = max(n, max(a, b));
  }

  int S = 1;
  for (int i = 1; i <= n; i++)
    if (d[i] & 1) {
      S = i;
      break;
    }

  dfs(S);
  for (int i = cnt - 1; i >= 0; i--)
    printf("%d\n", res[i]);
}

时间复杂度 O ( m n ) O(mn) O(mn),空间 O ( n ) O(n) O(n)

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值