CCF 2015-12-4 送货 100分

试题编号: 201512-4
试题名称: 送货
时间限制: 1.0s
内存限制: 256.0MB
问题描述:

问题描述

  为了增加公司收入,F公司新开设了物流业务。由于F公司在业界的良好口碑,物流业务一开通即受到了消费者的欢迎,物流业务马上遍及了城市的每条街道。然而,F公司现在只安排了小明一个人负责所有街道的服务。
  任务虽然繁重,但是小明有足够的信心,他拿到了城市的地图,准备研究最好的方案。城市中有n个交叉路口,m条街道连接在这些交叉路口之间,每条街道的首尾都正好连接着一个交叉路口。除开街道的首尾端点,街道不会在其他位置与其他街道相交。每个交叉路口都至少连接着一条街道,有的交叉路口可能只连接着一条或两条街道。
  小明希望设计一个方案,从编号为1的交叉路口出发,每次必须沿街道去往街道另一端的路口,再从新的路口出发去往下一个路口,直到所有的街道都经过了正好一次。

输入格式

  输入的第一行包含两个整数nm,表示交叉路口的数量和街道的数量,交叉路口从1到n标号。
  接下来m行,每行两个整数ab,表示和标号为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。 

千万别用递归!!因为题目最多有十万条边,若采用递归,层数最高会达到十万层,会导致计算机爆掉!用栈和循环进行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历年认证考试解答

猜你喜欢

转载自blog.csdn.net/qq_38632614/article/details/105177435