农场看守

题目描述

蒜头君最近做了农场看守,他每天晚上的工作就是巡视农场并且保证没有人破坏农场。从谷仓出发去巡视,并且最终回到谷仓。 蒜头君视力不太好,其他农场守卫只需要对农场的每一条连接不同场地的路走一遍就可以发现是不是有异常情况了。但是他很仔细和耐心,对农场的每一条连接不同场地的路需要走两遍,并且这两遍必须是不同的方向,因为他觉得应该不会两次都忽略农场中的异常情况。 每两块地之间一定至少有一条路连接。现在的任务就是帮他制定巡视路径。

输入描述

第一行输入两个整数 N,N(2≤N≤10000) 和 M,M(1≤M≤50000),表示农场一共有 N 块地 M 条边。 第二到M+1 行输入两个整数,表示对应的两块地之间有一条边。

输出描述

输出 2M+1 个数,一个数占一行,表示蒜头君巡查路径上地的标号,1 号为谷仓,从 1 开始,以 1 结束。如果有多种答案,输出任意一种。

样例输入

4 5
1 2
1 4
2 3
2 4
3 4

样例输出

1
2
3
4
2
1
4
3
2
4
1

思路

1.首先看到题目的时候我想的是,利用两次不同方向的深搜,然后再加上开始时的边结点就行了,比如样例,第一次深搜是1234然后再加上21.然后第二次换方向深搜,那就是1432然后再加上41就行了。首先这种想法我觉得还是挺好的,但是深搜的方向无法控制,我感觉,所以我在不同的深搜方向遇到了瓶颈。然后我想的是那就直接把第一次深搜的结果存在一个数组里面,这样就可以直接改变数组的元素的下标来产生第二种路径,但是对于原本只有一条边的图来说,比如说12,这种方法就会输出1221,没有到达预期的效果.而且对于结点个数不同,交换的自然也有很多很多的不同,所以把这种方法pass掉。
2.思路还是回到了第一步上,然后突然想起深搜一遍后回溯的时候他是会检测哪些结点是否被访问过。比如样例那个图第一次深搜它是1,2,3,4。那它回来的时候从4开始会检测 1是否被访问过,2是否被访问过,3是否被访问过,如果能再次记录这些结点即可。那就想到访问边了,访问过得边就记录为ture,这样结点就可以重复被记录了。
注意:
一定要在后面输出结点,否则有些数据将回不到1(谷仓),它会到某些结点就终止了。

AC代码


#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
const int maxn = 100001;
const int maxm = 500000;
struct edge{
    int v,pre;
}e[maxm];
int p[maxn],eid;
void init(){
    memset(p,-1, sizeof(p));
    eid = 0;
}
void insert(int u,int v){
    e[eid].v = v;
    e[eid].pre = p[u];
    p[u] = eid++;
}
bool vst[maxn];
void dfs(int u ){
    for(int i = p[u];i!=-1;i = e[i].pre){
        if(!vst[i]){
            vst[i]=true;
            dfs(e[i].v);
        }
    }
    cout<<u<<endl;
}

int main(){
    init();
    memset(vst,false, sizeof(vst));
    int n,m;
    cin>>n>>m;
    int u1,v1;
    for(int i = 0;i<m;i++){
        cin>>u1>>v1;
        insert(u1,v1);
        insert(v1,u1);
    }
    dfs(1);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值