題目描述
小 Y 是一個愛好旅行的 OIer。她來到 X 國,打算將各個城市都玩一遍。
小Y瞭解到, X國的 n 個城市之間有 m 條雙向道路。每條雙向道路連接兩個城市。 不存在兩條連接同一對城市的道路,也不存在一條連接一個城市和它本身的道路。並且, 從任意一個城市出發,通過這些道路都可以到達任意一個其他城市。小 Y 只能通過這些 道路從一個城市前往另一個城市。
小 Y 的旅行方案是這樣的:任意選定一個城市作爲起點,然後從起點開始,每次可 以選擇一條與當前城市相連的道路,走向一個沒有去過的城市,或者沿着第一次訪問該 城市時經過的道路後退到上一個城市。當小 Y 回到起點時,她可以選擇結束這次旅行或 繼續旅行。需要注意的是,小 Y 要求在旅行方案中,每個城市都被訪問到。
爲了讓自己的旅行更有意義,小 Y 決定在每到達一個新的城市(包括起點)時,將 它的編號記錄下來。她知道這樣會形成一個長度爲 n 的序列。她希望這個序列的字典序 最小,你能幫幫她嗎? 對於兩個長度均爲 n 的序列 A 和 B,當且僅當存在一個正整數 x,滿足以下條件時, 我們說序列 A 的字典序小於 B。
對於任意正整數1≤i<x,序列 A 的第 i 個元素 A_i和序列 B 的第 i 個元素 B_i相同。
序列 A 的第 x 個元素的值小於序列 B 的第 x 個元素的值。
輸入格式
輸入文件共 m+1 行。第一行包含兩個整數 n,m(m≤n),中間用一個空格分隔。
接下來 m 行,每行包含兩個整數 u,v(1≤u,v≤n) ,表示編號爲 u 和 v 的城市之 間有一條道路,兩個整數之間用一個空格分隔。
輸出格式
輸出文件包含一行,n 個整數,表示字典序最小的序列。相鄰兩個整數之間用一個 空格分隔。
輸入輸出樣例
輸入 #1
6 5
1 3
2 3
2 5
3 4
4 6
輸出 #1
1 3 2 5 4 6
輸入 #2
6 6
1 3
2 3
2 5
3 4
4 5
4 6
輸出 #2
1 3 2 4 5 6
說明/提示
【數據規模與約定】
對於100% 的數據和所有樣例, 1≤n≤5000 且 m=n−1 或 m=n 。
對於不同的測試點, 我們約定數據的規模如下:
解法:枚舉暴力刪邊
- 對於一個環,我們可以刪除這條邊,這樣就仍然可以用dfs了
- 我們在刪邊的時候,同時判斷這種情況是否可行和是否是最優解
AC代碼
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#define si 5050
#define re register int
using namespace std;
struct edge {
int nex,fro,to;
}e[si<<1];
int n,m,d,bx,by,cnt,k[si],ans[si],head[si];
vector<int> p[si]; bool v[si];
inline int read() {
int x=0,cf=1;
char ch=getchar();
while(ch<'0'||ch>'9') {
if(ch=='-') cf=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') {
x=(x<<3)+(x<<1)+(ch^48);
ch=getchar();
}
return x*cf;
}
inline void add(int x,int y) {
e[++cnt].to=y,e[cnt].fro=x,e[cnt].nex=head[x],head[x]=cnt;
}
inline void dfs(int x,int fa) {
if(v[x]) return;
v[x]=1,k[++d]=x;
for(re i=0;i<p[x].size();i++) {
int y=p[x][i]; if(y==fa) continue;
if((x==bx&&y==by)||(y==bx&&x==by)) continue;//刪邊
dfs(y,x);
}
}
inline void change() {
for(re i=1;i<=n;i++) ans[i]=k[i];
}
inline bool check() {
for(re i=1;i<=n;i++) {
if(k[i]>ans[i]) return false;
else if(k[i]<ans[i]) return true;
}
}
inline void fans(int x,int fa) {
ans[++d]=x;
for(re i=0;i<p[x].size();i++) {
int y=p[x][i];
if(y==fa) continue;
fans(y,x);
}
}
int main() {
n=read(),m=read();
for(re i=1;i<=m;i++) {
int x=read(),y=read();
add(x,y),add(y,x);
p[x].push_back(y);
p[y].push_back(x);
}
for(re i=1;i<=n;i++) {
sort(p[i].begin(),p[i].end());//尋找最優解
}
if(n==m) {
for(re i=0;i<cnt;i+=2) {
memset(v,false,sizeof(v));
d=0,bx=e[i].fro,by=e[i].to;
dfs(1,-1);
if(d<n) continue;//這時候圖不聯通
else if(!ans[1]) change();//如果還沒有解,那麼直接當作一個解
else if(check()) change();
}
for(re i=1;i<=n;i++) {
printf("%d ",ans[i]);
}
return 0;
}
fans(1,-1);
for(re i=1;i<=n;i++) {
printf("%d ",ans[i]);
}
return 0;
}