1. 拓扑排序问题(HDU 1285)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
public class Main
{
static int[] inDegree = new int[502];
static int[][] v = new int[502][502];
static boolean[] contain = new boolean[502];
public static void main(String[] args) throws IOException
{
StreamTokenizer in = new StreamTokenizer(new BufferedReader(
new InputStreamReader(System.in)));
int n, m;
while (in.nextToken() != StreamTokenizer.TT_EOF)
{
n = (int) in.nval;
in.nextToken();
m = (int) in.nval;
init(n);
for (int i = 1; i <= m; i++)
{
in.nextToken();
int p1 = (int) in.nval;
in.nextToken();
int p2 = (int) in.nval;
if(v[p1][p2] == 0)
{
inDegree[p2]++;
}
v[p1][p2] = 1;
}
topologicalOrder(n);
System.out.println();
}
}
private static void topologicalOrder(int n)
{
// TODO Auto-generated method stub
int vv;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (inDegree[j] == 0 && contain[j])
{
vv = j;
contain[vv] = false;
for (int j2 = 1; j2 <= n; j2++)
{
if (v[vv][j2] > 0)
{
inDegree[j2]--;
}
}
System.out.print(vv);
if(i != n)
{
System.out.print(" ");
}
break;
}
}
}
}
private static void init(int n)
{
// TODO Auto-generated method stub
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
v[i][j] = 0;
}
inDegree[i] = 0;
contain[i] = true;
}
}
}
上述代码就是最简单的拓扑排序,里面有很多可以优化的地方,比如用如果数据稀疏的话可以用邻接表来代替二维数组(矩阵),在找编号最小的且度为0的顶点,可以使用最小堆(
优先队列)。下面代码使用优先队列来代替原本的遍历查找,使复杂度降低。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.PriorityQueue;
import java.util.Queue;
public class Main
{
static int[] inDegree = new int[502];
static int[][] v = new int[502][502];
public static void main(String[] args) throws IOException
{
StreamTokenizer in = new StreamTokenizer(new BufferedReader(
new InputStreamReader(System.in)));
int n, m;
while (in.nextToken() != StreamTokenizer.TT_EOF)
{
n = (int) in.nval;
in.nextToken();
m = (int) in.nval;
init(n);
for (int i = 1; i <= m; i++)
{
in.nextToken();
int p1 = (int) in.nval;
in.nextToken();
int p2 = (int) in.nval;
if (v[p1][p2] == 0)
{
inDegree[p2]++;
}
v[p1][p2] = 1;
}
topologicalOrder(n);
System.out.println();
}
}
private static void topologicalOrder(int n)
{
// TODO Auto-generated method stub
int vv;
Queue<Integer> queue = new PriorityQueue<Integer>();
for (int i = 1; i <= n; i++)
{
if (inDegree[i] == 0)
{
queue.add(i);
}
}
for (int i = 1; i <= n; i++)
{
vv = queue.poll();
for (int j2 = 1; j2 <= n; j2++)
{
if (v[vv][j2] > 0)
{
inDegree[j2]--;
if (inDegree[j2] == 0)
{
queue.add(j2);
}
}
}
System.out.print(vv);
if (i != n)
{
System.out.print(" ");
}
}
}
private static void init(int n)
{
// TODO Auto-generated method stub
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
v[i][j] = 0;
}
inDegree[i] = 0;
}
}
}
直接把入度为0的顶点放到优先队列中(普通的拓扑排序只用普通队列/栈/数组即可,这里题目中有要求,相同入度为0的点要求序号小的先输出,所以使用优先队列),使用队列减少了一遍遍的遍历所有点的入度。
在使用BFS和Dijkstra的优先队列中都要使用到队列,关于Dijkstra以及最短路径算法,请查看最短路径算法
系列:
来源:oschina
链接:https://my.oschina.net/u/2243330/blog/626582