poj1780 Code 裸的欧拉回路

Code

忙了好久,终于搞定了,每次将不会的题琢磨完了,都感觉是一次小小的进步,庆祝一下下。。呵呵

首先是建图,题意要求所有的n位数编码成一个数字串,每个n位数只出现一次,可以把n位数看成边,那么可以把它的前n-1位看成点A,后n-1一位看成点B,那么它就是A->B的一条边了,这样我们就可以对10^(n - 1)个点建图,每个节点对另外10个点有边,找一次欧拉回路就行了。

这题有一难点,要求按最小字典序输出,我用邻接表存的边,然后对于每个点的链表是按字典序建的边,这样再用圈套圈算法,然后逆序输出,就可以求的最小序结果了。

还有个一个问题,如果递归写的话,就会系统栈爆栈,导致RE,所以需要我们改成非递归的形式,这点让我郁闷了好久。。 不过还是让我给改出来了,收获!让我对系统栈又有了更深的理解。

//============================================================================

// Description : 圈套圈算法,逆序输出欧拉回路

//============================================================================



#include <iostream>

#include<stdio.h>

#include<string.h>

#define NN 1000020

using namespace std;



typedef struct node{

	//int u;

	int v;

	int vis;

	struct node *nxt;

}NODE;



NODE *Link[NN / 10];

NODE edg[NN];

NODE *sta[NN]; // 模拟系统栈

int idx, kind, n, top;

int stk[NN];





void Init(){

	memset(Link, 0, sizeof(Link));

	idx = top = 0;

}



void Add(int u, int v){

	//edg[idx].u = u;

	edg[idx].v = v;

	edg[idx].vis = 0;

	edg[idx].nxt = Link[u];

	Link[u] = edg + idx++;

}



void dfs(int u){ // 递归形式

	for (NODE *p = Link[u]; p; p = p->nxt){

		if(!p->vis){

			p->vis = 1;

			Link[u] = p->nxt;

			dfs(p->v);

			stk[++top] = p->v % 10;

		}

	}

}



void dfs1(int u){ // 非递归形式

	int top0 = 0;

	NODE *p;

	sta[++top0] = Link[u];

	while(top0){

		for (p = sta[top0]; p; p = p->nxt){

			if(!p->vis){

				p->vis = 1;

				sta[top0] = p; // 递归进入下一层的时候,先保存入口

				sta[++top0] = Link[p->v]; //进入下一层

				Link[u] = p->nxt; // 更改链表头指针

				u = p->v; // 这点很重要,每次进入下一次递归的时候需要更改,否则不变

				break;

			}

		}

		if(p == NULL){

			top0--;

			if(top0 == 0) break;

			stk[++top] = sta[top0]->v % 10;

			sta[top0] = sta[top0]->nxt;

		}

	}

}

void Solve(){

	int i;

	dfs1(0);

	for (i = 1; i < n; i++){

		printf("0");

	}

	for (i = top;  i >= 1; i--){

		printf("%d", stk[i]);

	}

	puts("");

}

int main() {

	int i, j;



	while(scanf("%d", &n) != EOF){

		if(n == 0) break;

		if(n == 1){

			puts("0123456789");

			continue;

		}

		kind = 1; // kinds or number

		for (i = 1; i < n; i++){

			kind = kind * 10;

		}



		Init();

		int mod = kind / 10;

		for (i = 0; i < kind; i++){

			int tmp = i % mod;

			tmp *= 10;

			for (j = 9; j >= 0 ; j--){

				//if(tmp + j != i){

					Add(i, tmp + j);

				//}

			}

		}

		Solve();

	}

	return 0;

}

你可能感兴趣的:(code)