题解 P6145 【[USACO20FEB]Timeline G】
抢第一篇题解
这题思路主要是有些点必然在另外的点后执行.所以,我们可以做一个数组记录哪些点可以动(也就是没有点需要在他之前动).
在这个点动了之后,我们就将所有他所对应的点更新(也就是将那个点的限制条件-1).然后我们判断那个点的限制条件是否为0.如果为0,我们将其加入队列
每个点的最早动的时间就是他自己能动的最早值和每个在他之前动的点加上他俩距离的最大值
for (pp v : adj[qf]){
constrain[v.f]--;//限制条件--
pos[v.f] = max(pos[v.f],pos[qf]+v.s);//他自己本身的时间和在他前面动的点和他的时间差的最大值
if (constrain[v.f]==0) q.push(v.f);//如果没有限制条件了
}
为什么正确:
这个应该是dp的核心思想.如果某个点的所有有关联的数字都已经有了确定的值,那么这时候动这个点就100%是最小答案
完整代码:
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
#define pp pair<int,int>
#define f first
#define s second
int n,m,k;
int pos[100005];
vector<pp> adj[100005];
bool vis[100005];
int constrain[100005];
queue<int> q;
void setIO(string name) {
freopen((name+".in").c_str(),"r",stdin);
freopen((name+".out").c_str(),"w",stdout);
ios_base::sync_with_stdio(0);
}
int main(){
// setIO("timeline");
cin>> n >>m >> k;
for (int i=1;i<=n;i++) cin >> pos[i];
for (int i=0;i<k;i++){
int a,b,c; cin >> a >> b >> c;
adj[a].push_back(make_pair(b,c));
constrain[b]++;//要去的点的限制条件+1(因为假设a没去,我们不能判断b最早能动的时间)
}
for (int i=1;i<=n;i++) if (constrain[i]==0) q.push(i);//将所有没有限制条件的点放入队列
while(!q.empty()){
int qf = q.front();q.pop();
for (pp v : adj[qf]){
constrain[v.f]--;
pos[v.f] = max(pos[v.f],pos[qf]+v.s);
if (constrain[v.f]==0) q.push(v.f);
}
}
for (int i=1;i<=n;i++) cout << pos[i] << endl;//输出答案
}