poj1041 欧拉回路(值得好好看一下)

本文探讨了一个街道路线选择算法的问题,作者最初的方法在理解上存在误区,导致算法无法正确选择路径。通过对比和分析,作者最终采用递归算法解决了问题,实现了正确的路径选择。文中详细解释了算法实现过程,并提供了关键数据测试结果。

一开始按照自己的思路来。结果发现理解错误。题目说的是有多种可行方案时,选择编号较小的street。我以为每到一个节点,只能选择与该结点连接的还未访问过的编号最小的street。。。所以给的数据过了,还是WA。。。以下是错误代码

这组数据能通过:

1 1 1

1 1 2

1 1 3

1 1 5

1 1 4

0 0

输出:1 2 3 4 5

这组数据就通不过:

1 2 1

2 3 2

1 3 3

2 4 4

2 4 5

0 0

输出:1 4 5 2 3

原因是到结点2的时候选择了街道2而不是4,且没有回溯的过程

 

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;
const unsigned MaxJunc = 45;
const unsigned MaxStreet = 2000;
typedef struct _JUNC
{
	vector<unsigned> street;
}Junc;

int main()
{
	Junc junc[MaxJunc];
	unsigned street[MaxStreet][2];
	unsigned streetCnt, maxJuncNum;
	vector<unsigned> output;
	unsigned x,y,z;
	int i;

	while(1)
	{
		memset(junc, 0, sizeof(struct _JUNC)*MaxJunc);
		memset(street, 0, sizeof(unsigned)*MaxStreet*2);
		streetCnt = 0;
		maxJuncNum = 0;

		cin>>x>>y;
		if(x==0 && y==0)
			break;
		while(x!=0 && y!=0)
		{

			cin>>z;
			junc[x].street.push_back(z);
			junc[y].street.push_back(z);
			street[z][0] = x;
			street[z][1] = y;
			++streetCnt;
			if(x<y)
				maxJuncNum = maxJuncNum>y?maxJuncNum:y;
			else
				maxJuncNum = maxJuncNum>x?maxJuncNum:x;
			cin>>x>>y;
		}
		for(i=1; i<=maxJuncNum ; ++i)
		{
			vector<unsigned> tmp(junc[i].street.size());
			if(junc[i].street.size())
			{
				for(int j=0; j<junc[i].street.size(); ++j)
					tmp[j] = junc[i].street[j];

				sort(tmp.begin(),tmp.end());
				for(int j=0; j<junc[i].street.size();++j)
					junc[i].street[j] = tmp[j];
			}
		}
		
		i = 1;
		while(junc[i].street.size())
		{
			unsigned j = 0;
			unsigned visit;
			for(;j<junc[i].street.size(); ++j)//找的从junc[i]出发将要去的下一条street
			{
				if(junc[i].street[j]!=0)
				{
					visit = junc[i].street[j];
					junc[i].street[j] = 0;
					break;
				}
			}
			if(j==junc[i].street.size())
				break;
			output.push_back(visit);
			i = (i==street[visit][0])?street[visit][1]:street[visit][0];//跳到当前访问的street的另一端
			for(unsigned k=0; k<junc[i].street.size(); ++k)//将另一端中对应的该条street置为0
			{
				if(junc[i].street[k]==visit)
				{
					junc[i].street[k] = 0;
					break;
				}
			}
		}
		if(output.size()!= streetCnt)
			cout<<"Round trip does not exist."<<endl;
		else
		{
			cout<<output[0];
			for(i=1; i<output.size(); ++i)
				cout<<" "<<output[i];
			cout<<endl;
		}
		output.clear();
	}
	return 0;
}


参考别人的思路:http://blog.sina.com.cn/s/blog_48e3f9cd010002un.html 用递归

 欧拉回路:对于一个图可以从一个顶点沿着边走下去,每个边只走一次,所有的边都经过后回到原点的路。一个无向图存在欧拉回路的充要条件是每个顶点的度是偶数。

 

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;
const unsigned MaxJunc = 45;
const unsigned MaxStreet = 1995;

unsigned graph[MaxJunc][MaxStreet];
unsigned stack[MaxStreet];
unsigned juncDegree[MaxJunc];//保存结点的度
bool hasVisited[MaxStreet];
unsigned top,maxStreetNo;
void Euler(int s)
{
 int i;
 for(i = 1; i <= maxStreetNo; i ++)
 { 
  if(graph[s][i]  && !hasVisited[i])
  {
	   hasVisited[i] = true;      
	   Euler(graph[s][i]);
	   stack[top ++] = i;
  }
 }
}

int main()
{
	unsigned home;
	unsigned x,y,z;
	int i;

	while(1)
	{
		memset(graph, 0, sizeof(unsigned)*MaxJunc*MaxStreet);
		memset(stack, 0, sizeof(unsigned)*MaxStreet);
		memset(juncDegree, 0, sizeof(unsigned)*MaxJunc);
		memset(hasVisited, false, sizeof(bool)*MaxStreet);
		maxStreetNo = 0;
		top = 0;

		cin>>x>>y;
		home = min(x,y);
		if(x==0 && y==0)
			break;
		while(x!=0 && y!=0)
		{

			cin>>z;
			graph[x][z] = y;//x经过z到的y
			juncDegree[x]++;//结点x的度加1
			graph[y][z] = x;//y经过z到的x
			juncDegree[y]++;//结点y的度加1
			maxStreetNo = max(maxStreetNo, z);
			cin>>x>>y;
		}
		for(i=1; i<MaxJunc; ++i)//判断结点的度是否为偶数
			if(juncDegree[i]%2)
				break;

		if(i<MaxJunc)//有度不为偶数的结点
		{
			cout<<"Round trip does not exist."<<endl;
		}
		else
		{
			Euler(home);
			 for(i = top - 1; i >= 0; i --)
				 cout<<stack[i]<<" ";
			 cout<<endl;
		}
	}
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值