E. Speedrun

Problem - E - Codeforces

思路:分析题意知给定的图一定是一个有向无环图,所以能够使用拓扑序,在进行拓扑排序的途中统计一个维护一个完成当前任务的最小时间,那么入度为零的点就是一开始的时间,其他的点就是统计所有前驱的最大值max,表示至少在这个最大值之后它才能够完成这个任务,然后我们在看一下max%k与w[u]的关系,如果是大于关系,则代表要完成w[u]必须要到下一天了,因为这一天已经是max%k了,已经比w[u]大了;如果是小于关系,那么能够在这一天完成这个任务。那么我们现在就得到了每个点能够完成的最小的时间,那么统计最大值以及最小值相减就是答案吗?不是的,因为我们通过样例能够发现,我们可以讲某个入度为零的点延后一天完成,这样就使得最小值变大了,但是可能最大值会增加一点点,这样就能够使得差值变小了,那么我们能否枚举所有的入度为零的点,从小到达枚举,然后讲它们延后一天,统计出延后之后的最大值,然后减去最小值呢?这样做是可以的,我们发现每个点最多只会被延后一天(因为假如说u为当前的点,j为其前驱节点,那么如果其中某个j延后了一天,对于u来说,有两种情况,如果延后一天之后也不比它大,说明我u不用延后保持原来的即可,如果延后之后比它大了,说明我必须要延后一天了。但是出现了第二中状态以后,就不会再出现第二种状态了,因为原先u的完成时间是比所有的j都大的,那么如果u+k,那么对于所有的j来说,j+k一定也不会比u+k大了,所有一定是满足条件了,所以每个点最多只会被延后一天,所以每个节点最多只会被遍历一次),那么这样我们就能够保证修改的时间复杂度了,所以就可以直接暴力枚举了

cpp 复制代码
// Problem: E. Speedrun
// Contest: Codeforces - Pinely Round 2 (Div. 1 + Div. 2)
// URL: https://codeforces.com/contest/1863/problem/E
// Memory Limit: 256 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
#include<sstream>
#include<cassert>
#define fi first
#define se second
#define i128 __int128
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> PII;
const double eps=1e-7;
const int N=5e5+7 ,M=5e5+7, INF=0x3f3f3f3f,mod=1e9+7,mod1=998244353;
const long long int llINF=0x3f3f3f3f3f3f3f3f;
inline ll read() {ll x=0,f=1;char c=getchar();while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') {x=(ll)x*10+c-'0';c=getchar();} return x*f;}
inline void write(ll x) {if(x < 0) {putchar('-'); x = -x;}if(x >= 10) write(x / 10);putchar(x % 10 + '0');}
inline void write(ll x,char ch) {write(x);putchar(ch);}
void stin() {freopen("in_put.txt","r",stdin);freopen("my_out_put.txt","w",stdout);}
bool cmp0(int a,int b) {return a>b;}
template<typename T> T gcd(T a,T b) {return b==0?a:gcd(b,a%b);}
template<typename T> T lcm(T a,T b) {return a*b/gcd(a,b);}
void hack() {printf("\n----------------------------------\n");}

int T,hackT;
int n,m,k;
int w[N];
int h[N],e[M],ne[M],idx;
ll dist[N];
int din[N];
vector<int> son[N];
ll maxn=-1;

void add(int a,int b) {
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

void topsort() {
	queue<int> q;
	for(int i=1;i<=n;i++) {
		if(!din[i]) q.push(i);
	}
	
	while(q.size()) {
		auto it=q.front();
		q.pop();
		
		if(son[it].size()==0) dist[it]=w[it];
		else {
			ll sum=0;
			
			for(int i=0;i<son[it].size();i++) {
				int j=son[it][i];
				
				sum=max(sum,dist[j]);
			}
			
			if((sum%k)<=w[it]) sum+=w[it]-(sum%k);
			else sum+=k-(sum%k)+w[it];
			
			dist[it]=sum;
		}
		
		
		for(int i=h[it];i!=-1;i=ne[i]) {
			int j=e[i];
			
			din[j]--;
			if(din[j]==0) q.push(j);
		}
	}
}

void dfs(int u,ll &maxn) {
	dist[u]=dist[u]+k;
	maxn=max(maxn,dist[u]);
	for(int i=h[u];i!=-1;i=ne[i]) {
		int j=e[i];
		
		if(dist[j]>=dist[u]) continue;
		else dfs(j,maxn);
	}
}

void solve() {
	n=read(),m=read(),k=read();
	
	memset(h,-1,sizeof(int)*(n+4));
	memset(din,0,sizeof(int)*(n+4));
	idx=0;
	for(int i=1;i<=n;i++) w[i]=read(),son[i].clear(),dist[i]=0;
	
	maxn=-1;
	while(m--) {
		int a=read(),b=read();
		add(a,b);
		son[b].push_back(a);
		din[b]++;
	}
	
	vector<int> vis;
	for(int i=1;i<=n;i++) if(!din[i]) vis.push_back(i);
	
	topsort();
	
	for(int i=1;i<=n;i++) maxn=max(maxn,dist[i]);
	
	sort(vis.begin(),vis.end(),[&](int &a,int &b){
		return w[a]<w[b];
	});
	
	ll res=llINF;
	res=min(res,maxn-dist[vis[0]]);
	
	for(int i=0;i<vis.size()-1;i++) {
		dfs(vis[i],maxn);
		res=min(res,maxn-dist[vis[i+1]]);
	}
	
	printf("%lld\n",res);
}   

int main() {
    // init();
    // stin();
	// ios::sync_with_stdio(false); 

    scanf("%d",&T);
    // T=1; 
    while(T--) hackT++,solve();
    
    return 0;       
}          
相关推荐
2401_841495641 小时前
【计算机视觉】基于复杂环境下的车牌识别
人工智能·python·算法·计算机视觉·去噪·车牌识别·字符识别
Jonkin-Ma2 小时前
每日算法(1)之单链表
算法
晚风残2 小时前
【C++ Primer】第六章:函数
开发语言·c++·算法·c++ primer
杨云强2 小时前
离散积分,相同表达式数组和公式
算法
地平线开发者2 小时前
征程 6 | BPU trace 简介与实操
算法·自动驾驶
满天星83035772 小时前
【C++】AVL树的模拟实现
开发语言·c++·算法·stl
Lris-KK3 小时前
力扣Hot100--94.二叉树的中序遍历、144.二叉树的前序遍历、145.二叉树的后序遍历
python·算法·leetcode
麦麦鸡腿堡4 小时前
Java的动态绑定机制(重要)
java·开发语言·算法
zy_destiny4 小时前
【工业场景】用YOLOv8实现抽烟识别
人工智能·python·算法·yolo·机器学习·计算机视觉·目标跟踪
坚持编程的菜鸟4 小时前
LeetCode每日一题——螺旋矩阵
c语言·算法·leetcode·矩阵