试题编号: | 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。 |
千万别用递归!!因为题目最多有十万条边,若采用递归,层数最高会达到十万层,会导致计算机爆掉!用栈和循环进行DFS。
特别感谢百度知道给的思路灵感!
#include<iostream>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;
const int MAXV=10001;
int n,m;
bool vis[MAXV][MAXV]={false}; //bool类型做标记要比int节省空间 10000*10000不会爆!
vector<int> mp[MAXV],path;
//如果有海量数据排序的情况,用vector的赋值后排序的性能相对比set好。
//若有频繁的插入删除,(例如推荐系统那道题)最好用set
stack<int> stl;
int main(){
cin>>n>>m;
for(int i=0;i<m;i++){
int a,b;cin>>a>>b;
mp[a].push_back(b);
mp[b].push_back(a);
}
for(int i=1;i<=n;i++){
sort(mp[i].begin(),mp[i].end());
}
//如果直接开始无脑暴力DFS查找,数据量过大会导致超时,只有70分
//根据题意,这是一个欧拉通路问题 参考链接https://www.cnblogs.com/Ash-ly/p/5397702.html
//所以先进行图的判定,若满足欧拉图判定,才有通路,否则都没有通路
//无向图存在欧拉通路的两个条件 ①图连通并且度数为奇数的点的个数为0;
// 或者 ②图连通并且度数为奇数的的点可以有2个(其中一个一定是出发点)
stl.push(1); int i,u,v;
//注意!!!不能用递归!!不能用递归!!会爆掉!!!
//题目输出最多可以达到十万个,也就是说递归层次会达到十万层,计算机堆栈会爆掉
//通过循环进行DFS,相当于模拟递归!!
while(!stl.empty()){
u=stl.top();
for(i=0;i<mp[u].size();i++){//遍历每一个未被访问的边
v=mp[u][i];
if(vis[u][v]==false){
stl.push(v);
vis[u][v]=true;
vis[v][u]=true;
break;
}
}
if(i>=mp[u].size()){ //该点所有的边都访问过了
stl.pop();
path.push_back(u);
}
}
int count=0;
for(i=1;i<=n;i++){
if(mp[i].size()%2==1)
count++;
}
if((count!=0 && count!=2) || (count==2 && mp[1].size()%2==0) || path.size()!=m+1)
cout<<-1;
else{
for(i=path.size()-1;i>=0;i--)
cout<<path[i]<<" ";
}
}
更多相关CCF的试题解答,请点击>>CCF历年认证考试解答