#include using namespace std; const int N = 10010; int n; //必须完成的杂务的数目 int x; //工作序号 int y; //一些必须完成的准备工作 int ans; //最终结果 int a[N]; //完成工作所需要的时间a[x] int f[N]; //这个结点的最长时间 vector edge[N]; //出边链表 /** 测试数据: 7 1 5 0 2 2 1 0 3 3 2 0 4 6 1 0 5 1 2 4 0 6 8 2 4 0 7 4 3 5 6 0 答案: 23 */ /** * 功能:计算x号任务的最短完成时间 * @param x * @return */ /** 总结: 1、创建DAG的通用办法 2、注意谁是出发点,谁是终止点 3、深度优先搜索的应用,万能的魔法函数 4、记忆化搜索优化深度优先搜索 5、计算的是每个结点出发的最长链(自顶向下) */ int dfs(int x) { //记忆化搜索,防止重复计算 if (f[x]) return f[x]; //找到连接到这个结点的边的最长的一个 for (int i = 0; i < edge[x].size(); i++) f[x] = max(f[x], dfs(edge[x][i])); //加上本号任务的时长 f[x] += a[x]; //返回最短时间 return f[x]; } int main() { //创建DAG的标准套路 //需要完成的杂务的数目 cin >> n; for (int i = 1; i <= n; i++) { cin >> x >> a[x]; //完成工作所需要的时间len[x],注意:此处书中写的是len[i],也是可以AC的, // 原因是默认输入就是1,2,3...这样的输入,没有乱序输入。其实,如果没有乱序输入, // 这个cin>>x就是无用的,因为x肯定是等于i的。 while (cin >> y) { //需要完成的准备工作 if (!y) break; //由一个数字0结束 //前序啊!注意,这里是前序是谁!!!由谁到谁有一条有向边!!! edge[y].push_back(x); //这里要注意!!!! 是y向x有一条有向边,描述的是y是x的前序工作 !!!! } } //以上代码建图完毕!!!! //对于每项任务,分别计算最长工作时长,取最大值,就是最后的答案 for (int i = 1; i <= n; i++) ans = max(ans, dfs(i)); //输出大吉 cout << ans << endl; return 0; }