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;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章