本题中事件(顶点)为事件开始!!!区别于一般情况下事件结束。
#include<bits/stdc++.h>
using namespace std;
const int Max=1e5+7;
const int INF=INT_MAX;
const int Mod=1e9+7;
vector<int> graph[Max];
int indegree[Max];
long long ve[Max]; //记录顶点(事件开始)最早开始时间
long long vl[Max]; //记录顶点(事件开始)最晚开始时间
long long t[Max]; //事件花费时间 一般情况下是用结构体,本题用全局变量更好。
long long CriticalPath(int n) {
vector<int> topology; //拓扑排序,为求顶点(事件开始)最晚开始时间作准备
queue<int> node; //存放度为0的点
for(int i=1; i<=n; i++) {
if(indegree[i]==0) { //入度为0的点为实际源点
node.emplace(i);
}
}
long long totaltime=0;
while(!node.empty()) {
int u=node.front();
topology.emplace_back(u);
node.pop();
for(int i=0; i<graph[u].size(); i++) {
int v=graph[u][i];
ve[v]=max(ve[v],ve[u]+t[u]); //动态规划
indegree[v]--;
if(indegree[v]==0) {
node.emplace(v);
totaltime=max(totaltime,ve[v]+t[v]);
}
}
}
for(int i=topology.size()-1; i>=0; --i) {
int u=topology[i];
if(graph[u].size()==0) { //出度为0的点为实际汇点。
vl[u]=totaltime-t[u];
} else {
vl[u]=INF;
}
for(int j=0; j<graph[u].size(); j++) {
int v=graph[u][j];
vl[u]=min(vl[u],vl[v]-t[u]); //动态规划
}
}
return totaltime;
}
int main() {
int n,m;
while(cin>>n>>m) {
memset(graph,0,sizeof(graph));
memset(indegree,0,sizeof(indegree));
memset(ve,0,sizeof(ve));
memset(vl,0,sizeof(vl));
memset(t,0,sizeof(t));
for(int i=1; i<=n; i++) {
cin>>t[i];
}
for(int i=0; i<m; i++) {
int from,to;
cin>>from>>to;
graph[from].emplace_back(to);
indegree[to]++;
}
long long totaltime=CriticalPath(n);
long long answer=1;
for(int i=1; i<=n; i++) {
answer*=vl[i]-ve[i]+1;
answer%=Mod;
}
cout<<totaltime<<endl<<answer<<endl;
}
return 0;
}