CF1704E Count Seconds

E. Count Seconds

赛时绝杀了(((

我们算一下出度为 \(0\) 的节点 \(t\) 所需要排出多少次 \(1\)。通过简单的拓扑可以算出来,这非常简单。问题出在并不是时时刻刻这个节点上又有数字,那么就会造成耽搁,使得时间变长。那么有多少时间是耽搁的呢?

我们假设 \(dis_u\) 表示节点 \(u\)\(t\) 的最短距离。那么令 \(D=\max\limits_{i=1}^n {dis_u}\ \ a_u>0\)。耽搁的时间一定在 \(1\)\(D\) 之间。因为在时刻 \(D\) 之后,\(t\) 就会一直工作直到结束。这很好理解。\(D\leq m\),因此我们直接模拟即可。时间复杂度 \(O(m+m^2)\)

//Don't act like a loser.
//This code is written by huayucaiji
//You can only use the code for studying or finding mistakes
//Or,you'll be punished by Sakyamuni!!!
#include<bits/stdc++.h>
#define int long long
using namespace std;

int read() {
	char ch=getchar();
	int f=1,x=0;
	while(ch<'0'||ch>'9') {
		if(ch=='-')
			f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') {
		x=x*10+ch-'0';
		ch=getchar();
	}
	return f*x;
}
char read_char() {
	char ch=getchar();
	while(!isalpha(ch)) {
		ch=getchar();
	}
	return ch;
}

const int MAXN=1000+10,MOD=998244353;

int n,cnt,pp,m;
int a[MAXN],h[MAXN],ind[MAXN],oud[MAXN],f[MAXN],b[MAXN];
queue<int> q;
struct edge {
	int v,nxt;
}e[MAXN<<1];

void addedge(int u,int v) {
	e[++cnt].v=v;
	e[cnt].nxt=h[u];
	h[u]=cnt;
}

void topu() {
	for(int i=1;i<=n;i++) {
		if(!ind[i]) {
			q.push(i);
		}
	}
	
	while(!q.empty()) {
		int u=q.front();
		q.pop();
		for(int i=h[u];i;i=e[i].nxt) {
			int v=e[i].v;
			f[v]+=f[u];
			f[v]%=MOD;
			ind[v]--;
			if(!ind[v]) {
				q.push(v);
			}
		}
	}
}

signed main() {
	int t=read();
	while(t--) {
		cin>>n>>m;
		fill(h+1,h+n+1,0);
		fill(oud+1,oud+n+1,0);
		fill(ind+1,ind+n+1,0);
		cnt=0;
		for(int i=1;i<=n;i++) {
			f[i]=a[i]=b[i]=read();
		}
		for(int i=1;i<=m;i++) {
			int u,v;
			u=read();v=read();
			addedge(u,v);
			ind[v]++;
			oud[u]++;
		}
		for(int i=1;i<=n;i++) {
			if(!oud[i]) {
				pp=i;
			}
		}
		
		topu();
		int cnt=0;
		for(int tm=1;tm<=m;tm++) {
			bool ok=0;
			for(int i=1;i<=n;i++) {
				a[i]=b[i];
				if(b[i]) {
					b[i]--;
					ok=1;
				}
			}
			if(!ok) {
				break;
			}
			if(!a[pp]) {
				cnt++;
			}
			for(int u=1;u<=n;u++) {
				if(!a[u]) {
					continue;
				}
				a[u]--;
				for(int i=h[u];i;i=e[i].nxt) {
					int v=e[i].v;
					b[v]++;
				}
			}
		}
		
		int ans=f[pp]+cnt;
		ans=(ans+MOD)%MOD;
		cout<<ans<<endl;
	}
	
	return 0;
}

posted @ 2022-08-01 20:57  huayucaiji  阅读(93)  评论(0编辑  收藏  举报