P6145

[USACO20FEB]Timeline G

题目描述

Bessie 在过去的 \(M\) 天内参加了 \(N\) 次挤奶。但她已经忘了她每次挤奶是在哪个时候了。

对于第 \(i\) 次挤奶,Bessie 记得它不早于第 \(S_i\) 天进行。另外,她还有 \(C\) 条记忆,每条记忆形如一个三元组 \((a,b,x)\),含义是第 \(b\) 次挤奶在第 \(a\) 次挤奶结束至少 \(x\) 天后进行。

现在请你帮 Bessie 算出在满足所有条件的前提下,每次挤奶的最早日期。

保证 Bessie 的记忆没有错误,这意味着一定存在一种合法的方案,使得:

  • \(i\) 次挤奶不早于第 \(S_i\) 天进行,且不晚于第 \(M\) 天进行;
  • 所有的记忆都得到满足;

输入格式

第一行三个整数 \(N,M,C\)。保证 \(1 \leq N,C \leq 10^5\)\(2 \leq M \leq 10^9\)

接下来一行包含 \(N\) 个整数 \(S_1, S_2 , \ldots, S_n\),保证 \(\forall 1 \leq i \leq n\),都满足 \(1 \leq S_i \leq M\)

下面 \(C\) 行每行三个整数 \(a,b,x\),描述一条记忆。保证 \(a \neq b\),且 \(1 \leq x \leq M\)

输出格式

输出 \(N\) 行,每行一个整数,第 \(i\) 行的数表示第 \(i\) 次挤奶的最早日期。

样例 #1

样例输入 #1

4 10 3
1 2 3 4
1 2 5
2 4 2
3 4 4

样例输出 #1

1
6
3
8

差分约束系统

几个注意点:

1.求的是最早时间 所以跑最长路

2.由于有 s[i]的要求 所以 超级源点建边时 add(0,i,s[i])

#include<bits/stdc++.h>
using namespace std; 
#define int long long
int n,m,c;
const int N=1e5+5;
struct Graph{
	int nxt,to,val;
}edge[N<<1];
int head[N],cnt,vis[N],dis[N],in[N];
inline void add(int u,int v,int w)
{
	cnt++;
	edge[cnt].to=v;
	edge[cnt].nxt=head[u];
	edge[cnt].val=w;
	head[u]=cnt;
}
bool spfa(int s)
{
	queue<int>q;
	q.push(s);
	memset(dis,-1,sizeof(dis));//跑最长路 所以初始化赋值赋小 
	dis[s]=0;
	vis[s]=1;
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(int i=head[u];i;i=edge[i].nxt)
		{
			int v=edge[i].to;
			int w=edge[i].val;
			if(dis[u]+w>dis[v])
			{
				dis[v]=dis[u]+w;
				if(!vis[v])
				{
					vis[v]=1;
					q.push(v);
					in[v]++;
					if(in[v]>n+1)return false;
				}
			}
		}
	}
	return true;
}
signed main()
{
	ios::sync_with_stdio(false);
	//由于求的是最早时间 所以跑最长路
	//还有 超级源点与i的距离为 s[i] 不是 0
	cin>>n>>m>>c;
	for(int i=1;i<=n;i++)
	{
		int x;
		cin>>x;
		add(0,i,x);//超级源点建边	
	}
	for(int i=1;i<=c;i++)
	{
		int a,b,x;
		cin>>a>>b>>x;
		add(a,b,x);
	}
	int pd=spfa(0);
	for(int i=1;i<=n;i++)
		cout<<dis[i]<<"\n";
	return 0;
}
posted @ 2023-04-15 22:50  N0zoM1z0  阅读(13)  评论(0编辑  收藏  举报