zoukankan      html  css  js  c++  java
  • UVA302 John's trip

    John有很多朋友住在不同的街,想去拜访每位朋友,同时希望走的路最短。因为道路很窄,John在一条路上不能往回走。

    John希望从家出发,拜访完所有的朋友之后回到自己的家,且总路程最短。John意识到如果可以每条路径都走一次,然后返回起点,应该是最短的路径。写一个程序帮助John找到这样的路径。

    给出的每条街连接两个路口,最多有1995条街(编号从1到n),44个路口(编号从1到m)。

    裸的欧拉回路题,可以不用(dfs)

    我们用两个栈,一个用来模拟,一个用来记答案。因为答案要求保证字典序最小的那一组,所以我们先对与每个点相连的点按从小到大排序,这样先选编号小的点,就可以保证找到的第一组答案就是字典序最小的那一组答案了。

    小优化:当我们访问完一条边后,把当前选的这个点连的边删除,这样就可以保证每次访问的边都是未访问过的边了,时间复杂度也由(O(N×M))降为了(O(N+M))

    还有最要注意的一点就是每一组解行末无空格。(被卡了好久= =)

    Code

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <vector>
    using namespace std;
    struct edge
    {
    	int to,id;
    }stk[10000];
    int st,d[50],n,ans[10000],num,top,vis[10000],m;  //d存每个点的度,如果有度数是奇数的点,那么肯定无欧拉回路.
    vector <edge> a[50];
    int cmp(edge x,edge y)
    {
    	return x.id<y.id;
    }
    void euler(int s)       //找欧拉回路
    {
    	stk[++top].to=s;    //模拟栈
    	vector <edge>::iterator it;
    	while (top>0)
    	{
    		int u=stk[top].to,w=stk[top].id,fl=0;
    		for (it=a[u].begin();it!=a[u].end();it++)
    		{
    			int v=(*it).to,i=(*it).id;
    			if (!vis[i])     //vis代替删边
    			{
    				fl=1;
    				stk[++top].to=v;
    				stk[top].id=i;
    				vis[i]=1; 
    				break;       //进入下一层
    			}
    		}
    		if (!fl)        //回溯
    		{
    			top--;
    			ans[++num]=w;    //更新答案栈
    		}
    	}
    }
    void clear()
    {
    	for (int i=1;i<=n;i++)
    		a[i].clear(),d[i]=0,vis[i]=0;
    	for (int i=1;i<=1995;i++)
    		vis[i]=0;
    	num=0;
    	m=0;
    }
    int main()
    {
    	int x,y,z;
    	cin>>x>>y;
    	while (x||y)
    	{
    		clear();
    		int fl=0;
    		cin>>z;
    		n=max(x,y);
    		st=min(x,y);
    		m++;
    		a[x].push_back((edge){y,z});
    		a[y].push_back((edge){x,z});
    		d[x]++;
    		d[y]++;
    		cin>>x>>y;
    		while (x||y)
    		{
    			cin>>z;
    			a[x].push_back((edge){y,z});
    			a[y].push_back((edge){x,z});
    			n=max(max(x,y),n);
    			d[x]++;
    			d[y]++;
    			m++;
    			cin>>x>>y;
    		}
    		for (int i=1;i<=n;i++)
    			if (d[i]%2!=0)
    			{
    				cout<<"Round trip does not exist."<<endl;
    				fl=1;
    				break;
    			}
    		if (!fl)
    		{
    			for (int i=1;i<=n;i++)
    				sort(a[i].begin(),a[i].end(),cmp);//排序保证解的字典序最小
    			euler(st);
    			for (int i=num-1;i>=2;i--)
    				cout<<ans[i]<<" ";
    			cout<<ans[1]<<endl;
    		}
    		cin>>x>>y;
    		cout<<endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    php IE中文乱码
    Ehab and a 2-operation task (思维题)
    9-7链表数据求和操作
    "巴卡斯杯" 中国大学生程序设计竞赛
    Codeup 问题 B: 算法7-16:弗洛伊德最短路径算法
    一只小蜜蜂...
    结构体作为函数参数(值传递,引用传递,指针传递)
    Codeforces Round # 515 (div.3) A. Vova and Train
    查找最大元素
    JSP复习(part 4)
  • 原文地址:https://www.cnblogs.com/sdlang/p/13068110.html
Copyright © 2011-2022 走看看