問題描述
爲了增加公司收入,F公司新開設了物流業務。由於F公司在業界的良好口碑,物流業務一開通即受到了消費者的歡迎,物流業務馬上遍及了城市的每條街道。然而,F公司現在只安排了小明一個人負責所有街道的服務。
任務雖然繁重,但是小明有足夠的信心,他拿到了城市的地圖,準備研究最好的方案。城市中有n個交叉路口,m條街道連接在這些交叉路口之間,每條街道的首尾都正好連接着一個交叉路口。除開街道的首尾端點,街道不會在其他位置與其他街道相交。每個交叉路口都至少連接着一條街道,有的交叉路口可能只連接着一條或兩條街道。
小明希望設計一個方案,從編號爲1的交叉路口出發,每次必須沿街道去往街道另一端的路口,再從新的路口出發去往下一個路口,直到所有的街道都經過了正好一次。
輸入格式
輸入的第一行包含兩個整數n, m,表示交叉路口的數量和街道的數量,交叉路口從1到n標號。
接下來m行,每行兩個整數a, b,表示和標號爲a的交叉路口和標號爲b的交叉路口之間有一條街道,街道是雙向的,小明可以從任意一端走向另一端。兩個路口之間最多有一條街道。
輸出格式
如果小明可以經過每條街道正好一次,則輸出一行包含m+1個整數p1, p2, p3, …, pm+1,表示小明經過的路口的順序,相鄰兩個整數之間用一個空格分隔。如果有多種方案滿足條件,則輸出字典序最小的一種方案,即首先保證p1最小,p1最小的前提下再保證p2最小,依此類推。
如果不存在方案使得小明經過每條街道正好一次,則輸出一個整數-1。
樣例輸入
4 5
1 2
1 3
1 4
2 4
3 4
樣例輸出
1 2 4 1 3 4
樣例說明
城市的地圖和小明的路徑如下圖所示。
樣例輸入
4 6
1 2
1 3
1 4
2 4
3 4
2 3
樣例輸出
-1
樣例說明
城市的地圖如下圖所示,不存在滿足條件的路徑。
評測用例規模與約定
前30%的評測用例滿足:1 ≤ n ≤ 10, n-1 ≤ m ≤ 20。
前50%的評測用例滿足:1 ≤ n ≤ 100, n-1 ≤ m ≤ 10000。
所有評測用例滿足:1 ≤ n ≤ 10000,n-1 ≤ m ≤ 100000。
/*
歐拉路徑
1.判斷連通性,判斷結點度數(0個或2個結點度數爲奇數)
2.若連通,其歐拉路徑
*/
#include<iostream>
#include<fstream>
#include<vector>
#include<stack>
#include<algorithm>
#include<cstring>
#define N 10005
using namespace std;
int n, m;
stack <int> s; //DFS2棧
vector <int> G[N]; //鄰接表
int vis[N]; //結點是否訪問
bool map[N][N]; //邊是否訪問
//檢查圖的連通性
void DFS1( int u ){
vis[u] = 1;
for( int i = 0; i < G[u].size(); i++ ){
int v = G[u][i];
if( vis[v] == 0 ){
DFS1( v );
}
}
}
//求取歐拉路徑
void DFS2( int u ){
for( int i = 0; i < G[u].size(); i++ ){
int v = G[u][i];
if( !map[u][v] ){ //未訪問過的邊
map[u][v] = 1;
map[v][u] = 1;
DFS2( v );
s.push( v ); //後處理,逆序push
}
}
}
int main(){
int a, b; //標號爲a的交叉路口和標號爲b的交叉路口之間有一條街道
int count = 0; //度數爲奇數的結點個數
memset( G, 0, sizeof(G) );
memset( vis, 0, sizeof(vis) );
memset( map, 0, sizeof(map) );
// ifstream fin("00.txt", ios::in);
ifstream fin("01.txt", ios::in);
// ifstream fin("02.txt", ios::in);
fin >> n >> m;
// cin >> n >> m;
for( int i = 0; i < m; i++ ){
fin >> a >> b;
// cin >> a >> b;
G[a].push_back(b);
G[b].push_back(a);
}
// 1.判斷圖的連通性
DFS1( 1 );
for( int i = 1; i <= n; i++ ){
if( vis[i] == 0 ){
cout << -1;
return 0;
}
}
// 2.判斷結點度數(0個或2個結點度數爲奇數)
for( int i = 1; i <= n; i++ ){
sort( G[i].begin(), G[i].end() );
if( G[i].size() % 2 == 1 ){
count++;
}
}
if( count == 0 || count == 2 ){
if( count == 2 && G[1].size() % 2 == 0 ){
cout << -1;
return 0;
}
DFS2( 1 );
}else{
cout << -1;
return 0;
}
s.push( 1 );
while( !s.empty() ){
cout << s.top() << " ";
s.pop();
}
return 0;
}