方法一
// csp 202212-2 训练计划
// 100分
// 要注意一个节点可能回受到后面多个节点的影响
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int N = 370;
int n, m;
int rely[N], a[N];
int res[N], sum[N]; // res最早的时间, sum记录一条路径上累积的时间,用于判断是否超时
int st[N]; // 是否被依赖的 其实可以用哈希表去记录被哪些依赖
int ans[N]; // ans最迟的时间
int main()
{
cin >> n >> m;
for (int i = 1; i <= m; i ++ )
{
cin >> rely[i];
st[rely[i]] = true; // 被依赖
}
for (int i = 1; i <= m; i ++ ) cin >> a[i];
bool flag = true;
for (int i = 1; i <= m; i ++ )
{
if (!rely[i])
{
res[i] = 1;
sum[i] = a[i];
}
else
{
int k = rely[i];
res[i] = res[k] + a[k];
sum[i] = sum[k] + a[i]; // 记录这条路径上累积的时间
}
if (sum[i] > n) flag = false;
}
for (int i = 1; i <= m; i ++ )
cout << res[i] << ' ' ;
cout << endl;
if (flag)
{
for (int i = m; i >= 1; i -- ) // 从后往前
{
int temp = 400;
for (int j = i + 1; j <= m; j ++ )
if (rely[j] == i)
temp = min(temp, ans[j]);
// 一个节点可能会受到后面多个节点的影响,要找到最小的依赖它的
if (temp == 400)
ans[i] = n - a[i] + 1;
else
ans[i] = temp - a[i];
}
for (int i = 1; i <= m; i ++ )
cout << ans[i] << " ";
}
// 错误
// if (flag)
// {
// for (int i = m; i >= 1; i -- )
// if (!st[i]) // 未被依赖
// {
// int k = a[i];
// int j = i;
// while (true)
// {
// if (ans[j])
// ans[j] = min(n - k + 1, ans[j]); // 出现更新,会进而影响前面的节点结果,不正确。
// else
// ans[j] = n - k + 1;
// k += a[rely[i]];
// j = rely[j];
// if (j == 0) break;
// }
// }
// for (int i = 1; i <= m; i ++ )
// cout << ans[i] << " ";
// }
return 0;
}
方法二:求最晚时间采用DFS方法
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 370;
int n, m;
int rely[N], t[N];
int res[N], res2[N];
vector<int> g[N];
// 可以看成一棵树
void dfs(int u)
{
if (g[u].size() == 0)
{
res2[u] = n - t[u] + 1;
return;
}
int minv = 400;
for(auto i: g[u])
{
dfs(i);
minv = min(minv, res2[i] - t[u]);
}
res2[u] = minv;
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= m; i ++ )
{
cin >> rely[i]; // 每个节点依赖的节点
g[rely[i]].push_back(i); // 每个节点的后序节点
}
for (int i = 1; i <= m; i ++ )
cin >> t[i];
bool flag = true;
for (int i = 1; i <= m; i ++ )
{
if(rely[i] == 0) res[i] = 1; // 没有依赖
else
res[i] = res[rely[i]] + t[rely[i]];
if (res[i] + t[i] - 1 > n) flag = false; // 超过最大天数
}
for (int i = 1; i <= m; i ++ )
cout << res[i] << " ";
cout << endl;
// 可以继续计算最晚时间
if (flag)
{
dfs(0);
for (int i = 1; i <= m; i ++ )
cout << res2[i] << " ";
}
return 0;
}