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

UVa 872 - Ordering 输出全拓扑排序

时间: 2024-10-06 19:12:15

UVa 872 - Ordering 输出全拓扑排序的相关文章

UVA - 10305 - Ordering Tasks (拓扑排序!)

UVA - 10305 Ordering Tasks Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu Submit Status Description Problem F Ordering Tasks Input: standard input Output: standard output Time Limit: 1 second Memory Limit: 32 MB John has n task

UVA 10305 Ordering Tasks (拓扑排序)

题意:给你n个点.m个关系,每个关系两个点u.v,表示u小于v,叫你输出任意一个序列保证满足所有给定的关系 例如:n=3 m=2 1 2 3 1 3 2 3 1 2 题解:拓扑排序排的是一个有向无环图(DAG),首先没有回路,否则会失败,其次如果存在G(u,v),则在该序列中u在v前面 实现方法就是遍历每个点,当此点没被标记过就进入递归 然后将此点看做树的根节点(DAG其实可以看做森林),遍历它可以到的所有点,最后从后向前将点加入排序的序列并标记 #include<cstdio> #inclu

UVA - 10305 Ordering Tasks(拓扑排序)

题意:给定优先关系进行拓扑排序. 分析:将入度为0的点加入优先队列,并将与之相连的点入度减1,若又有度数为0的点,继续加入优先队列,依次类推. #pragma comment(linker, "/STACK:102400000, 102400000") #include<cstdio> #include<cstring> #include<cstdlib> #include<cctype> #include<cmath> #i

UVa 10305 - Ordering Tasks【拓扑排序】

Ordering Tasks John has n tasks to do. Unfortunately, the tasks are not independent and the execution of one task is only possible if other tasks have already been executed. Input The input will consist of several instances of the problem. Each insta

Uva 10305 Ordering Tasks(拓扑排序模版题)

Uva 10305 #include<iostream> #include<queue> #define pb push_back #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double pi=acos(-1.0); const int N=1e2+5; using namespace std; int n,m; int du[N]; vector<int>

UVa 1572 Self-Assembly (构造+拓扑排序。。。。。)

题意:给定n个带标号的正方形,标号要么是一个大写字母加一个+或-,要么是00, 当且仅当大写字母相同并且符号相反时可以连接,问你给定的能不能拼成一个无限大的的东西. 析:说实话,真心没有看出来是拓扑排序,后来知道是,可是还是不会写. 既然要拼成无限大,那么只要拼的时候拼出一个环来,又由于每个是无限多的,那么可以一直重复, 就能拼起来无限大的东西,把每个正方形看成一条边,那么不就是一个拓扑排序,看看能不能找到一个环么, 如果能找到,那么就可以,找不到,就不可以.注意的是正方形可以从四面都拼,所以要

UVA - 12263 Rankings 模拟(拓扑排序)

1 #pragma comment(linker, "/STACK:1000000000") 2 #include <bits/stdc++.h> 3 #define LL long long 4 #define INF 0x3f3f3f3f 5 #define IN freopen("E.in","r",stdin); 6 #define OUT freopen("out.txt", "w",

poj 4084:拓扑排序

poj 4084:拓扑排序 很好的题目,恶心的算法 描述 给出一个图的结构,输出其拓扑排序序列,要求在同等条件下,编号小的顶点在前. 输入 若干行整数,第一行有2个数,分别为顶点数v和弧数a,接下来有a行,每一行有2个数,分别是该条弧所关联的两个顶点编号. v<=100, a<=500 输出 若干个空格隔开的顶点构成的序列(用小写字母). 样例输入 6 8 1 2 1 3 1 4 3 2 3 5 4 5 6 4 6 5 样例输出 v1 v3 v2 v6 v4 v5 解题方案 显然这是有向图,然

hello大家好,我是拓扑排序

发几个以前写的拓扑排序,回顾一下. 拓扑排序,一般不会单独考,主要要求还是掌握好这个概念,有个感性的认识,以及能快速的写出求拓扑排序的程序,进而继续接下来对图的处理,或是比如dp之类的算法,又或者是判断有无环之类.求拓扑序主要就是运用队列,push入度为0的点,删掉它们出去的边,重复这个操作.像要是求字典序最小,就可以用优先队列. TOJ 3993 求字典序最小的拓扑排序 1 #include<cstdio> 2 #include<queue> 3 #include<cstr