FZU 2227 邮票【离散化+欧拉路径】

 Problem 2227 邮票

Accept: 52    Submit: 152
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

2
1 100
100 2
3
3 1
100 2
3 2

 Sample Output

1 100 2
1 3 2 100

 Source

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

思路:有n条无向边,输出要求的是最小字典序的n+1个点,我们在纸上画画也不难理解,想用n条边连接n+1个点,而且还能保证从某一个点出发遍历其他所有的点的话,那么这条路一定是一条欧拉路经。


对于无向图的欧拉路径  :起点终点的度为1,其间道路上的点的度都为2.

对于输出按照最小字典序输出:因为起点和终点的编号不可能相同,所以比对一下度为1的点哪个节点编号比较小,我们从这个节点开始Dfs找一条欧拉路径即可。


AC代码:


#include<stdio.h>
#include<string.h>
#include<map>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
vector<int >a[1000005];
int degree[100005];
int ans[100005];
int vis[100005];
int tt;
void Dfs(int u)
{
    vis[u]=1;
    ans[tt++]=u;
    for(int i=0;i<a[u].size();i++)
    {
        int v=a[u][i];
        if(vis[v]==0)Dfs(v);
    }
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        tt=0;
        map<int ,int >mp;
        map<int ,int>fmp;
        for(int i=1;i<=n+1;i++)a[i].clear();
        memset(vis,0,sizeof(vis));
        memset(ans,-1,sizeof(ans));
        memset(degree,0,sizeof(degree));
        int cont=1;
        for(int i=0;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if(mp[x]==0)
            {
                fmp[cont]=x;
                mp[x]=cont++;
            }
            if(mp[y]==0)
            {
                fmp[cont]=y;
                mp[y]=cont++;
            }
            a[mp[x]].push_back(mp[y]);
            a[mp[y]].push_back(mp[x]);
            degree[mp[x]]++;
            degree[mp[y]]++;
        }
        for(int i=1;i<cont;i++)
        {
            if(degree[i]==1)
            {
                memset(vis,0,sizeof(vis));
                Dfs(i);
                break;
            }
        }
        for(int i=0;i<tt;i++)
        {
            ans[i]=fmp[ans[i]];
        }
        int flag=0;
        if(ans[0]>ans[tt-1])reverse(ans,ans+tt);
        for(int i=0;i<tt;i++)
        {
            if(i==0)printf("%d",ans[i]);
            else printf(" %d",ans[i]);
        }
        printf("\n");
    }
}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值