poj1949(拓扑,dp)
2017-05-08 17:03
375 查看
点击打开题目链接
大意:
有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);
}
}
大意:
有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);
}
}
相关文章推荐
- POJ 1949 Chores(树状DP)
- POJ 1949 Chores(树形dp)
- POJ-1949(模拟或DP)
- POJ1949 DP基础题
- [poj 1949]Chores 题解 [dp]
- (POJ DP1.1)POJ 1949 Chores(简单DP)
- POJ 1949 DP?
- POJ 1949 DP?
- (POJ 1949)Chores DAG简单DP
- POJ 1949 Chores(DP)
- POJ 1155 TELE 树形DP(背包)
- poj1260 dp
- poj 1837 Balance(DP 01背包)
- poj 1948 dp(组成面积最大的三角形)
- 【dp】Making the Grade POJ - 3666
- POJ 2955 Brackets (区间DP,括号匹配)
- POJ 1163 The Triangle DP 逐点累加
- POJ 3687 Labeling Balls 【逆拓扑】
- Football - POJ 3071 概率dp
- poj 3254 Corn Fields【状态压缩dp-入门】