题目描述:
小翟为了完成一篇论文,一共要抄袭n篇文章。其中第i篇文章需要a[i]的时间去完成。小翟可以发动粉丝同时抄袭多篇文章,但存在一些文章,只有当它的若干个前置文章抄袭完成后,才能开始抄袭该文章。同时我们认为小翟和其粉丝在一篇文章的前置文章都完成后,能马上开始抄袭该文章。为了让小翟尽快完成论文,获得博士学位,在最优的情况下,小翟的论文什么时候可以完成?
小翟虽然不知道知网,但是他想知道在保证论文尽快完成的情况下(即保证上题答案不变情况),每篇文章最早什么时候可以开始抄袭,和最晚什么时候可以开始抄袭。设第i篇文章最早可以抄袭的时间为f[i];在不影响论文完成时间前提下,第i篇文章最晚可以抄袭的时间为g[i]. 请你回答∏i=0-n (g[i]-f[i]+10) 除以10^9+7所得的余数,题目保证有解。
输入:
第一行输入一个整数n,m
第二行输入n个正整数,a1,a2,…,an描述每篇文章抄袭所需要的时间。
接下来读入m行,每行读入两个整数u,v,表示编号为u的文章是编号为v文章的前置文章
所有的输入数据都满足1<=n<=5*105,1<=m<=106,1<=a[i]<=10^6
输出:
第一行输出一个整数表示论文最早完成时间。
第二行输出一个整数表示∏i=0-n (g[i]-f[i]+10) 除以10^9+7所得的余数
样例输入:
8 9
11 17 16 20 14 12 13 15
1 3
2 4
4 3
3 6
5 6
2 5
6 8
5 7
7 8
样例输出:
80
459599979
备注:
∏i=0-n 为i从0到n的累乘符号
分析:
拓扑排序,关键路径,反向计算最长可能结果。
因为只有题目没有oj 通过了样例不确定代码是不是对的。
仅为保存代码,代码思路仅供参考
代码:
#include <stdio.h>
#include <iostream>
#include <vector>
#include <queue>
#define MAX 1000000007
#define INF 0x3fffffff
using namespace std;
int n,m;
int indegree[50050]={0};//入度
int outdegree[50050]={0};//出度
int tcin[50050];//耗时
vector<int> g[50050];//正向
vector<int> rg[50050];//反向
int tm[50050];//最短时间
int tm2[50050];//最长时间
int pre[50050];//关键路径的前驱
bool vis[50050];
//vector<int> toporder;
int checkvis(int v){
int res=INF;
for(int i=0;i<g[v].size();i++){
if(vis[g[v][i]]==false) return 0;
else res=min(tm2[g[v][i]]-tcin[g[v][i]],res);
}
return res;
}
void calmx(int e){
int temp=e;
queue<int> q;
while(temp!=0){
tm2[temp]=tm[temp];
q.push(temp);
vis[temp]=true;
temp=pre[temp];
}
for(int i=1;i<=n;i++){
//所有出度为0的点 时间均为tm2[e]
if(outdegree[i]==0){
tm2[i]=tm2[e];
vis[i]=true;
}
}
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=0;i<rg[u].size();i++){
int v=rg[u][i];
int tempres;
if(vis[v]) continue;
tempres=checkvis(v);
if(tempres){
tm2[v]=tempres;
vis[v]=true;
q.push(v);
}
}
}
}
void toplogicalsort(){
queue<int> q;
for(int i=1;i<=n;i++){
if(indegree[i]==0){
q.push(i);
}
}
while(!q.empty()){
int u=q.front();
q.pop();
// toporder.push_back(u);
for(int i=0;i<g[u].size();i++){
int v=g[u][i];
indegree[v]--;
if(indegree[v]==0){
q.push(v);
}
if(tm[u]+tcin[v]>tm[v]){
tm[v]=tm[u]+tcin[v];
pre[v]=u;
}
}
}
}
int findlast(){
int mx=0,ans=0;
for(int i=1;i<=n;i++){
if(tm[i]>mx){
mx=tm[i];
ans=i;
}
}
return ans;
}
int main(){
// freopen("1.txt","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&tcin[i]);
tm[i]=tcin[i];
}
int a,b;
for(int i=0;i<m;i++){
scanf("%d%d",&a,&b);
g[a].push_back(b);
rg[b].push_back(a);
indegree[b]++;
outdegree[a]++;
}
toplogicalsort();
int e=findlast();
calmx(e);
long long sum=1;
for(int i=1;i<=n;i++){
sum=sum*(tm2[i]-tm[i]+10);
sum=sum%MAX;
}
printf("%d\n%lld\n",tm[e],sum);
return 0;
// for(int i=1;i<=n;i++){
// printf("%d:%d-%d=%d\n",i,tm2[i],tm[i],tm2[i]-tm[i]);
// }
// printf("TOPOrder:");
// for(int i=0;i<toporder.size();i++) printf(" %d",toporder[i]);
// cout<<endl;
// for(int i=1;i<=n;i++) printf("pre:%d:%d\n",i,pre[i]);
// cout<<endl;
// printf("%d",3459600000%MAX);
}