P1113 杂务
显然地,本题中各项工作是有一定的依赖条件的,也就是说我们在进行工作 X 之前可能需要先进行一些其他的工作。
而完成工作 X 所需的时间和所有 X 所依赖的工作完成的时间的最大值有关。(应该还好理解吧)
在这道题中,我们可以列出一个简单的 DP 转移方程:
$$f_i=\max\{pre_i\}+a_i$$
其中 \(f_i\) 为从最开始到进行完第 \(i\) 项任务所需的时间, \(pre_i\) 为 \(i\) 号结点的前驱数组, \(a_i\) 为做第 \(i\) 件事所需的时间。
但是,我们如果直接进行 dfs 遍历,可能会出现一个问题:在我们计算 \(f_i\) 的时候,还存在没有计算过的 \(pre_i\),从而导致结果计算错误。
那么,我们在计算的时候,应该确保在计算一个结点 \(u\) 时,所有与连向它的点都已经被计算过。
而实现这一过程就利用到:拓扑排序
const int N=1e5+10;
vector<int> g[N];
int din[N];
int cost[N];
int f[N];
int n;
int topo()
{
queue<int> q;
int res=0;
for(int i=1;i<=n;i++)
if(!din[i])
{
q.push(i);
f[i]=cost[i];
res=max(res,f[i]);
}
while(q.size())
{
int t=q.front();
q.pop();
for(int i=0;i<g[t].size();i++)
{
int j=g[t][i];
f[j]=max(f[j],f[t]+cost[j]);
res=max(res,f[j]);
if(--din[j] == 0) q.push(j);
}
}
return res;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
int a,t;
cin>>a>>cost[i];
int x;
while(cin>>x && x)
g[x].push_back(a),din[a]++;
}
cout<<topo()<<endl;
//system("pause");
}