刚开始使用的深搜,只能得70分,深搜的思路是先判断图是否联通以及是否为0或2个点为奇数度,然后直接深搜一遍路径,耗时主要在深搜上,搜索的时候有很多路由于是重复进行的导致浪费时间,而 使用了网上的一种Hierholzer’s Algorithm算法后,算法优势主要在于记录每条走不通的路,这样在最后找完所有边的时候就能够直接将ans数组和circuit数组拼接起来就行,这样只需要把每条边遍历一次就行,时间复杂度为O(E),最后也得了满分
试题编号: | 201512-4 |
试题名称: | 送货 |
时间限制: | 1.0s |
内存限制: | 256.0MB |
问题描述: | 问题描述 为了增加公司收入,F公司新开设了物流业务。由于F公司在业界的良好口碑,物流业务一开通即受到了消费者的欢迎,物流业务马上遍及了城市的每条街道。然而,F公司现在只安排了小明一个人负责所有街道的服务。 输入格式 输入的第一行包含两个整数n, m,表示交叉路口的数量和街道的数量,交叉路口从1到n标号。 输出格式 如果小明可以经过每条街道正好一次,则输出一行包含m+1个整数p1, p2, p3, ..., pm+1,表示小明经过的路口的顺序,相邻两个整数之间用一个空格分隔。如果有多种方案满足条件,则输出字典序最小的一种方案,即首先保证p1最小,p1最小的前提下再保证p2最小,依此类推。 样例输入 4 5 样例输出 1 2 4 1 3 4 样例说明 城市的地图和小明的路径如下图所示。 样例输入 4 6 样例输出 -1 样例说明 城市的地图如下图所示,不存在满足条件的路径。 评测用例规模与约定 前30%的评测用例满足:1 ≤ n ≤ 10, n-1 ≤ m ≤ 20。 |
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<climits>
#include<queue>
#include<map>
#include<string>
#include<set>
#include<vector>
#define rep(i, x, n) for(int i = x; i < n; i++)
const int INF = INT_MAX;
const int maxn = 10001;
const int maxm = 100001;
using namespace std;
int n, m, s;
set<int> adjs[maxn];
bool vis[maxn][maxn];
vector<int> ans;
int main(){
freopen("data.txt", "r", stdin);
scanf("%d%d", &n, &m);
rep(i, 0, m){
int u, v;
scanf("%d %d", &u, &v);
adjs[u].insert(v);
adjs[v].insert(u);
}
int cnt = 0, ok = 1;
rep(i, 1, n+1){
if(adjs[i].size() & 1)
cnt++;
}
if((cnt!=0 && cnt != 2) || (cnt == 2 && adjs[1].size() & 1 != 1)){
printf("-1");
return 0;
}
vector<int> circuit;
ans.push_back(1);
while(!ans.empty() && ans.size()+circuit.size()< m+1){
int u = ans.back();
if(adjs[u].empty()){
circuit.push_back(u);
ans.pop_back();
}else{
auto it = adjs[u].begin();
ans.push_back(*it);
adjs[*it].erase(u);
adjs[u].erase(*it);
}
}
if(ans.empty()){
printf("-1");
return 0;
}
else{
while (!circuit.empty()) {
ans.push_back(circuit.back());
circuit.pop_back();
}
rep(i, 0, ans.size()) printf("%d ", ans[i]);
return 0;
}
}