NOI 2004 沙丘 dune

首先,由于已访问的每个点的度数都是已知的,可以通过记录从根到当前点的路径上每个点所走的弧的编号(设为cur_arc[path[i]],i为深度)来回到根结点(walk(degree[path[i]] - cur_arc[path[i]]))。

如果原图是一棵树,可以直接做,相当于模拟DFS。(因为树上DFS只要不走通往父节点的边,就不必判重)。

 

下面考虑如何判断环,并记录下相应的后向边:

如图,DFS搜索树上,AB是后向边。如果现在已经在B放置了一个标记,那么从A向根走,会经过B。此时可以知道有一个环,但不知道在B上边BA的序号。因此从B拿到标记后退回A,在A处放标记,再回到B,枚举B的每一条出边,直到到达一个有标记的点,则此时枚到的边为BA。在此边做上不可访问的标记,并回到A。

 

因此,扩展每个点的时(例如从M走到N),先在新走到的点(N)上放上标记,在从原来的点(M)向根走,如果中途没遇到有标记的点,则说明N是未访问的点,回到N开始DFS;如果遇到一个有标记的点,则发现了环,标记相应的后向边后从M枚举N的下一个点。

 

另外还有一个问题,1号点的0号边是不确定的。我的解决办法是,先调用walk(0),再dfs,然后判断一下dfs所得的root的0号边是否被标记为不可访问,如果不是,就调用walk(0)并再次dfs。

 

实现中很多细节非常纠结,还好数据比较厚道,构造出来就给了10分。

 

 

 

  Problem: dune
    Point    Execution Status     Score         Time [sec]    Memory [kb] 
    1        Normal               10.000        0.007         2360        
    2        Normal               10.000        0.060         3212        
    3        Normal               10.000        0.006         2364        
    4        Normal               10.000        0.007         2412        
    5        Normal               10.000        0.006         2488        
    6        Normal               10.000        0.007         2412        
    7        Normal               10.000        0.008         2652        
    8        Normal               10.000        0.008         2660        
    9        Normal               10.000        0.016         2840        
    10       Normal               10.000        0.025         3180

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值