FZU Problem 2227 邮票

 Problem 2227 邮票

Accept: 30    Submit: 68
Time Limit: 1000 mSec    Memory Limit : 32768 KB

 Problem Description

一天Bob收到一封信。Bob知道瓦罗兰大陆的邮局从A城市送信到B城市,乐意使用从A城市到B城市的邮票(A, B),或者使用从B城市到A城市的邮票(A, B),但是由于瓦罗兰大陆的城市繁多,所以并不是所有城市之间都能直接发送接收信件,换句话说,某两个城市想要通行邮件必须经过其他城市才行,但是邮局发送一次邮件的路途中从不会通过一座城市两次。

现在在Bob的信封上有N个邮票,Bob想知道这封信件是如何周转到达他手中的。

 Input

题目有多组数据。

每组数据第一行包含一个整数,N ( 2 <= N <= 1e5),代表信件上的N封邮票。

接下有N行数据。第 i 行数据包含两个整数 ui,vi,代表从城市ui发送到城市vi的邮票,ui代表城市的编号,每个城市的编号互不相同,(ui != vi ,1 <= ui, vi <= 1e9)。

输入数据保证有解。

 Output

每组样例的结果输出为一行, 每行包括N+1个被空格隔开的整数,代表着信件依次经过的城市编号。

若有多组可行答案,输出字典序最小的那组答案。

 Sample Input

21 100100 233 1100 23 2

 Sample Output

1 100 21 3 2 100

 Source

FOJ有奖月赛-2016年4月(校赛热身赛)


思路:通过题意我们可以知道在输入数据中值只出现一次的便是起点或者终点(肯定只有两个点,因为该题的路径就是一条链),因为输出的是字典序最小的所以那两个点中值小的为起点而值相对大的为终点,但1 <= ui, vi <= 1e9,不能开那么大的数组,用STL中的map来离散化就可以了。找到起点和终点后,用STL中的set来二分通过当前路径的终点去查找起点,并打印路径。做了这题后,顿时感觉STL的强大。。Orz

代码:

#include <cstdio>
#include <cstring>
#include <utility>
#include <map>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
typedef long long ll;
#define maxn (int)1e5
pair<int,int>point[maxn];
set<pair<int,int> >s1;
map<int,int>mp1,mp2,mp3;
int main()
{
#ifdef CDZSC_June
	freopen("t.txt","r",stdin);
#endif // CDZSC_June
	int n,p;
	while(~scanf("%d",&n))
	{
		mp1.clear();mp2.clear();
		s1.clear();mp3.clear();
		p = 1;
		for(int i = 0; i<n; i++)
		{
			scanf("%d%d",&point[i].first,&point[i].second);
			s1.insert(point[i]);
			s1.insert(make_pair(point[i].second, point[i].first));//因为路径的双向的
			if(mp1[point[i].first] == NULL){
				mp1[point[i].first] = p;
				mp2[p] =point[i].first; 
				mp3[p] = 1;
				p++;
			}
			else{
				mp3[mp1[point[i].first]]++;
			}
			if(mp1[point[i].second] == NULL){
				mp1[point[i].second] = p;
				mp2[p] =point[i].second; 
				mp3[p] = 1;
				p++;
			}
			else{
				mp3[mp1[point[i].second]]++;
			}
		}
		int s = -1,t = -1;
		for(int i = 0 ;i<p; i++){//只出现一次的为起点或终点
			if(mp3[i] == 1 ){
				if(s == -1){
					s = mp2[i];
				}
				else{
					t = mp2[i];
				}
			}
		}
		if(s > t) swap(s,t);//使小的为起点,大的为终点
		printf("%d",s);
		set<pair<int,int> >::iterator it,itt,temp,itt1;
		it = s1.lower_bound(make_pair(s,0));
		while(s1.size() > 2)
		{
			itt = s1.lower_bound(make_pair(it->second,0));
			itt1 = s1.lower_bound(make_pair(it->second,it->first));
			s = itt->first;
			temp = it;
			if(s1.size() > 2){
				printf(" %d",s);
			}
			s1.erase(temp);
			s1.erase(itt1);
			it = s1.lower_bound(make_pair(s,0));
		}
		printf(" %d\n",t);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值