poj1949(拓撲,dp)

點擊打開題目鏈接

大意:

有n個任務,第i個任務需要時間xi來完成,並且第i個任務必須在它 “前面的” 某些任務完成之後才能開始。

給你任務信息,問你最短需要多少時間來完成任務。


這道題做完了以後感覺分類不太清晰,看了網上,有說拓撲排序,大多都是說是dp。

我先是想到拓撲排序的,感覺遞推自然而然就用上了,dp[i]=max(dp[j]+t[i]) (j是i之前要完成的任務)(*)

這道題寫寫,代碼跟拓撲也差不多了,順帶複習複習拓撲,括號內鏈接我覺得不錯(拓撲學習鏈接

引用下面一段:

Kahn算法:

摘一段維基百科上關於Kahn算法的僞碼描述:

L← Empty list that will contain the sorted elements
S ← Set of all nodes with no incoming edges
while S is non-empty do
    remove a node n from S
    insert n into L
    foreach node m with an edge e from nto m do
        remove edge e from thegraph
        ifm has no other incoming edges then
            insert m into S
if graph has edges then
    return error (graph has at least onecycle)
else 
    return L (a topologically sortedorder)

 

不難看出該算法的實現十分直觀,關鍵在於需要維護一個入度爲0的頂點的集合:

每次從該集合中取出(沒有特殊的取出規則,隨機取出也行,使用隊列/棧也行,下同)一個頂點,將該頂點放入保存結果的List中。

緊接着循環遍歷由該頂點引出的所有邊,從圖中移除這條邊,同時獲取該邊的另外一個頂點,如果該頂點的入度在減去本條邊之後爲0,那麼也將這個頂點放到入度爲0的集合中。然後繼續從集合中取出一個頂點…………


這道題不是要求出拓撲序,按照上面的算法,隊列已經保證了拓撲序了。此時u->v,如果u要出隊的話,剛好可以

用上面的(*)式更新val[v](用於求v任務完成的最短時間)

最後答案顯然就是max(val[num])(1<=num<=n)


代碼如下:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
import java.util.Vector;

class Reader {
	static BufferedReader reader;
	static StringTokenizer tokenizer;

	static void init(InputStream input) {
		reader = new BufferedReader(new InputStreamReader(input));
		tokenizer = new StringTokenizer("");
	}

	static String next() throws IOException {
		while (!tokenizer.hasMoreTokens()) {
			tokenizer = new StringTokenizer(reader.readLine());
		}
		return tokenizer.nextToken();
	}

	static int nextInt() throws IOException {
		return Integer.parseInt(next());
	}
}

public class Main {

	/**
	 * @param args
	 */
	static int n, num, head, max;
	static int p[], t[], innum[], val[];
	static int pre[][];
	static Queue<Integer> queue;
	static Vector<Integer> vector[];

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		Reader.init(System.in);
		n = Reader.nextInt();
		p = new int[n + 1];
		t = new int[n + 1];
		val = new int[n + 1];
		pre = new int[n + 1][];
		innum = new int[n + 1];
		vector = new Vector[n + 1];
		for (int i = 1; i <= n; i++)
			vector[i] = new Vector<Integer>();
		for (int i = 1; i <= n; i++) {
			t[i] = Reader.nextInt();
			p[i] = Reader.nextInt();
			pre[i] = new int[p[i] + 1];
			innum[i] = p[i];
			for (int j = 1; j <= p[i]; j++) {
				num = Reader.nextInt();
				pre[i][j] = num;
				vector[num].add(i);
			}
		}
		queue = new LinkedList<Integer>();
		for (int i = 1; i <= n; i++)
			if (innum[i] == 0) {
				queue.offer(i);
				val[i] = t[i];
			}
		while (!queue.isEmpty()) {
			head = queue.poll();
			Iterator<Integer> iter = vector[head].iterator();
			while (iter.hasNext()) {
				num = iter.next();
				if (val[num] < val[head] + t[num])
					val[num] = val[head] + t[num];
				innum[num]--;
				if (innum[num] == 0)
					queue.offer(num);
			}
		}
		max = 0;
		for (int i = 1; i <= n; i++)
			if (val[i] > max)
				max = val[i];
		System.out.println(max);
	}

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章