首页 > 代码库 > UVa 872 - Ordering 输出全拓扑排序

UVa 872 - Ordering 输出全拓扑排序

本题要求输出全部拓扑排序的序列。

还好本题的数据量不是很大,限制在26个大写英文字母,故此可以使用递归法输出。

这个递归输出全部解在Leetcode很多这样的题目的,不小心的话,还是很难调试的。

总体考了递归和拓扑排序,还有判断是否可以拓扑排序-就是是否图有环。

考了三大知识点,难度还是有的。因为数据量不大,故此判断环可以使用一般递归方法,递归只需要注意细节就好了。


#include <stdio.h>
#include <vector>
#include <string.h>
using namespace std;
const int ALPHA = 26;
bool gra[ALPHA][ALPHA];
int id = 0, len = 0;
const int MAX_B = 512;
char buf[MAX_B];

char getFromBuf()
{
	if (id >= len)
	{
		len = fread(buf, 1, MAX_B, stdin);
		id = 0;
	}
	return buf[id++];
}

struct Subset
{
	int p, r;
};

Subset subs[ALPHA];

int findParent(int u)
{
	if (u != subs[u].p) subs[u].p = findParent(subs[u].p);
	return subs[u].p;
}

void unionTwo(int x, int y)
{
	int xroot = findParent(x);
	int yroot = findParent(y);
	if (subs[xroot].r < subs[yroot].r) subs[xroot].p = yroot;
	else
	{
		subs[yroot].p = xroot;
		if (subs[yroot].r == subs[xroot].r) subs[xroot].r++;
	}
}

void initSubs()
{
	for (int i = 0; i < ALPHA; i++)
	{
		subs[i].p = i;
		subs[i].r = 0;
	}
}

bool isCycle()
{
	initSubs();
	for (int i = 0; i < ALPHA; i++)
	{
		for (int j = 0; j < ALPHA; j++)
		{
			if (i == j || !gra[i][j]) continue;
			int ip = findParent(i);
			int jp = findParent(j);
			if (ip == jp) return true;
			unionTwo(i, j);
		}
	}
	return false;
}

int rs[ALPHA];
bool vis[ALPHA];
void printAllTopologicalOrders(int N, int rsid = 0)
{
	if (rsid == N)	//递归到底了,打印结果
	{
		if (rsid > 0) putchar(rs[0]+'A');
		for (int i = 1; i < rsid; i++)
		{
			putchar(' ');
			putchar(rs[i]+'A');
		}
		putchar('\n');
		return ;
	}
	for (int i = 0; i < ALPHA; i++)
	{
		if (vis[i]) continue;//这里要判断,漏了这句,好难dubg啊。要仔细用脑去模拟过程才能发现!!!
		if (!gra[i][i]) continue;	//没有这个点,跳过
		int j = 0;
		for ( ; j < ALPHA; j++)//检查i是否有入度
		{
			if (i != j && !vis[j] && gra[j][i]) break;
		}
		if (j == ALPHA) //找到入度为零的点i了
		{
			vis[i] = true;
			rs[rsid] = i;
			printAllTopologicalOrders(N, rsid+1);
			vis[i] = false;
		}
	}
}

int main()
{
	int T;
	scanf("%d", &T);
	while (T--)
	{
		int N = 0;
		memset(gra, 0, sizeof(gra));
		char a = getFromBuf();
		while ((a == '\n' || a == ' ') && len) a = getFromBuf();
		while (a != '\n' && len)
		{
			if ('A' <= a && a <= 'Z')
			{
				gra[a-'A'][a-'A'] = 1;//代表有点
				N++;
			}
			a = getFromBuf();
		}

		while ((a == '\n' || a == ' ') && len) a = getFromBuf();
		while (a != '\n' && len)
		{
			int u = a - 'A';
			a = getFromBuf(); a = getFromBuf();
			int v = a - 'A';

			gra[u][v] = 1;

			a = getFromBuf();
			if (a == '\n') break;
			a = getFromBuf();
		}
		fill(vis, vis+ALPHA, false);
		if (isCycle()) puts("NO");
		else
		{
			printAllTopologicalOrders(N);
		}
		if (T) putchar('\n');
	}
	return 0;
}