大家好我试图解决这个问题http://uva.onlinejudge.org/index.php?option=onlinejudge&page=show_problem&problem=813并且我意识到它想要获得拓扑排序问题的所有解决方案,我知道如何只获得一个可能的解决方案,这就是我的代码{{3 }}
static ArrayList<Integer> [] arr;
static int visited [];
static Stack<Integer> a = new Stack<Integer>();
static boolean flag=false;
public static void graphcheck(int node){ //method to check if there is a cycle in the graph
visited[node] = 2;
for(int i=0;i<arr[node].size();i++){
int u =arr[node].get(i);
if(visited[u]==0){
graphcheck(u);
}else if(visited[u]==2){
flag=true;
return;
}
}
visited[node] = 1;
}
public static void dfs2(int node){ //method to get one possible topological sort which I want to extend to get all posibilites
visited[node] = 1;
for(int i=0;i<arr[node].size();i++){
int u =arr[node].get(i);
if(visited[u]==0){
dfs2(u);
}
}
a.push(node);
}
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int tc = Integer.parseInt(br.readLine());
for(int k=0;k<tc;k++){
br.readLine();
String h[]= br.readLine().split(" ");
int n= h.length;
arr=new ArrayList[n];
visited = new int[n];
for( int i = 0; i < n; i++) {
arr[ i] = new ArrayList<Integer>();
}
String q[]=br.readLine().split(" ");
int y=q.length;
for(int i=0;i<y;i++){
int x=0;
int z=0;
for(int j=0;j<n;j++){
if(q[i].charAt(0)==h[j].charAt(0)){
x=j;
}else if(q[i].charAt(2)==h[j].charAt(0)){
z=j;
}
}
if(q[i].charAt(1)=='<'){
arr[x].add(z);
}
}
for(int i=0;i<n;i++){
if(visited[i]==0)
graphcheck(i);
}
if(flag){
System.out.println("NO");
}else{
a.clear();
Arrays.fill(visited, 0);
for(int i=0;i<n;i++){
if(visited[i]==0){
dfs2(i);
}
}
int z= a.size();
for(int i=0;i<z;i++){
int x =a.pop();
System.out.print(h[x]+" ");
}
System.out.println();
}
}
}
答案 0 :(得分:2)
一种可能的方法是修改Khan, (1962)指定的算法,其中使用以下算法计算拓扑排序:
L←包含已排序元素的空列表
S←没有入边的所有节点的集合
虽然S非空,但
remove a node n from S insert n into L for each node m with an edge e from n to m do remove edge e from the graph if m has no other incoming edges then insert m into S
如果图形有边缘,那么
return error (graph has at least one cycle)
其他
return L (a topologically sorted order)
这会计算一个拓扑排序,以便生成所有可能的排序。要获得所有可能的排序,您可以将结果视为树,其中根是第一个节点,节点的每个子节点都是下一个值之一。给出一个图表:
1 -> 3 -> 8
| | |
| v |
| 7 |
| \ |
| \_ v
+--> 5 -> 9
树可能看起来像:
1
/ \
3 5
/|\ |
7 8 9 9
| |
9 9
然而,在重新阅读您的问题之后:
给出形式A&lt;的形式的变量约束的列表。 B,您要编写一个程序,打印与约束一致的变量的所有顺序。例如,给定约束A&lt; B和A&lt; C有两个变量A,B和C的顺序与这些约束一致:ABC和ACB。
我不相信这个解决方案会为您提供您正在寻找的答案,但我们非常欢迎您尝试并实施它。
另请查看this algorithm。
注意:的
在重新阅读你的问题之后我不打算发布这个,但是我决定反对它,因为这些信息可能对你有用。
祝你好运。答案 1 :(得分:1)
为将来的观众添加解决方案:
要打印拓扑排序的所有解决方案,我们遵循以下方法:
将所有顶点初始化为未标记。
现在选择未标记的顶点并且具有零indegree并将所有顶点的indegree减少1(对应于删除边缘)。
现在将此顶点添加到列表并再次调用递归函数并回溯。
从标记,列表和indegree的函数重置值返回后,枚举其他可能性。
以下代码 -
[self.viewContainer addSubview: classLoadedFromNib];
classLoadedFromNib.frame = self.viewContainer.frame;
来源:http://www.geeksforgeeks.org/all-topological-sorts-of-a-directed-acyclic-graph/
答案 2 :(得分:-1)
这是我必须基于其他算法构建的唯一非递归工作代码,因为递归在处理图算法时确实是一个糟糕的解决方案,即使它是自然的。相反,我们可以在拓扑排序和回溯的每一层保留一个未访问的集合,甚至不需要额外的堆栈,只有这个数据结构。时间复杂度基本上与递归版本相同,例如最坏情况 O((m+n)*n!)。当然,排列 {1..n} 的所有 $n!$ 排列并调用简单的 O(m+n) is_topological_sort
函数在平均情况下会变慢,并且不能用于解决足够大的挑战问题。
def topo_khan_enum(g): #O((m+n)*n!)
topo, S, k = [], set(), 0
inc = {u: 0 for u in g}
for u in g:
for v in g[u]: inc[v] += 1
for u in g:
if inc[u] == 0: S.add(u)
unprocessed = {0: set(S)}
while len(unprocessed[k]) != 0:
while len(S) != 0:
u = unprocessed[k].pop(); S.remove(u); k += 1
topo.append(u)
for v in g[u]:
inc[v] -= 1
if inc[v] == 0: S.add(v)
unprocessed[k] = set(S)
if k < len(g): raise ValueError
yield list(topo)
while True:
u = topo.pop(); k -= 1
for v in g[u]:
if inc[v] == 0: S.remove(v)
inc[v] += 1
S.add(u)
if k == 0 or len(unprocessed[k]) != 0: break
return ()