1. 程式人生 > 實用技巧 >P5022 旅行

P5022 旅行

2018年NOIP提高組day2t1

題目簡意:n個點m條邊的圖,從1號城市開始訪問其他城市,訪問方法分兩種,以選擇一條與當前城市相連的道路,走向一個沒有去過的城市,或者沿著第一次訪問該 城市時經過的道路後退到上一個城市。在每到達一個新的城市時,將它的編號記錄下來作為字典序。要求所有城市都訪問過以後的最小字典序.

輸入:  輸出:1 3 2 5 4 6
6 5 
1 3 
2 3 
2 5 
3 4 
4 6

輸入: 輸出:1 3 2 4 5 6
6 6 
1 3 
2 3 
2 5 
3 4 
4 5 
4 6
說明:n<=5000,一部分資料是m = n-1, 另一部分是m=n

解析: 本題考查的是搜尋+環的判定+細節處理。

程式碼1:是一棵樹,可以發現訪問一個點,必須將該點的子樹都訪問完再訪問別的子樹。如果訪問該點後去訪問其他子樹,根據兩種訪問方式的要求,該點子樹將無法再次訪問。所有城市都訪問的要求無法滿足。因此,迴圈與該點相連的點,找到編號最小的進行訪問,深搜後回溯。
/*
不存在兩條連線同一對城市的道路,->沒有重邊
也不存在一條連線一個城市和它本身的道路。-> 沒有自環
並且, 從任意一個城市出發,通過這些道路都可以到達任意一個其他城市。->一定連通
*/
#include<iostream>
#include<cstdio>
#include<cmath>
#include
<cstring> #include<algorithm> #include<queue> #include<cstdlib> using namespace std; int n,m,cnt,hd[5005],vis[5005],tot,f[5005],num[5005]; struct Edge{ int to,nxt; }edge[10000];// void add(int u, int v){ cnt++; edge[cnt].to = v; edge[cnt].nxt = hd[u]; hd[u] = cnt; num[u]
++; } int t ; void dfs(int u){ printf("%d ",u); int tot = 1; while(tot <= num[u]){ int mv = n+1; tot++; for(int i = hd[u]; i ; i = edge[i].nxt){ int v = edge[i].to; if(num[u]==1 && vis[v]) return; if(!vis[v] && v < mv) mv = v; } if(mv < n+1){//mv發生了變化 vis[mv] = 1; dfs(mv); } } } int main(){ scanf("%d%d",&n,&m); int x,y; for(int i = 1; i <= m; i++){ scanf("%d%d",&x,&y); add(x,y); add(y,x); } vis[1] = 1; dfs(1); return 0; }