题目描述

Time Limit: 1000 ms

Memory Limit: 256 mb

小H为了完成一篇论文,一共要完成n个实验。其中第i个实验需要ai的时间去完成。

小H可以同时进行若干实验,但存在一些实验,只有当它的若干前置实验完成时,才能开始进行该实验。

同时我们认为小H在一个实验的前置实验都完成时,就能马上开始该实验。

为了让小H尽快完成论文,需要知道在最优的情况下,最后一个完成的实验什么时候完成?

小H还想知道,在保证最后一个实验尽快完成的情况下(即保证上一问的答案不变),他想知道每个实验最晚可以什么时候开始。

设第i个实验最早可能的开始时间为fi,不影响最后一个实验完成时间的最晚开始时间为gi,请你回答

除以10^9+7所得的余数。

题目保证有解。

输入输出格式

输入描述:

从标准输入读入数据。

第一行输入一个整数n,m。

第二行输入n个正整数,a1,a2,…an,描述每个实验完成所需要的时间。

接下来读入m行,每行读入两个整数u,v,表示编号为u的实验是编号为v的实验的前置实验。

对于所有的输入数据,都满足1<=n<=10^5, 1<=m<=5*10^5, 1<=ai<=10^6。

输出描述:

输出到标准输出。

第一行输出一个整数表示最晚完成的实验的时间。

第二行输出一个整数表示除以10^9+7所得的余数。

输入输出样例

输入样例#:

复制

7 5

11 20 17 10 11 17 17

5 4

6 1

7 3

2 4

2 1

输出样例#:

复制

3 4

7840

提示

第一个点最早开始时间为20,最晚开始时间为23。

第二个点最早开始时间为0,最晚开始时间为3。

第三个点最早开始时间为17,最晚开始时间为17。

第四个点最早开始时间为20,最晚开始时间为24。

第五个点最早开始时间为0,最晚开始时间为13。

第六个点最早开始时间为0,最晚开始时间为6。

第七个点最早开始时间为0,最晚开始时间为0。

题目来源

清华大学2019年机试题

//本题相当于计算关键路径 但比关键路径简单

//没有生成拓扑序列和逆拓扑序列 而是直接求了

#include

#include

#include

typedef struct test{

int indegree;

int outdegree;

int beg;

int end;

int cost;

}test;

#define INF 0x3f3f3f3f

#define vMAX 100001

#define mod 1000000007

#define max(a,b) ((a)>(b)?(a):(b))

#define min(a,b) ((a)

//不能直接开这么大的数组

//int mp[vMAX][vMAX];

//test v[vMAX];

//int vis[vMAX];

int main(){

int n,m,i,j,k,a,b,f=0,t,late=0;

long sum=1;//要用long 不然会超

scanf("%d %d",&n,&m);

int mp[n+1][n+1];

test v[n+1];

int vis[n+1];

//初始化

memset(mp,INF,sizeof(mp));

for(i=1;i<=n;i++){

v[i].indegree=v[i].outdegree=v[i].beg=v[i].cost=0;

v[i].end=INF;

}

//输入

for(i=1;i<=n;i++) scanf("%d",&v[i].cost);

for(i=0;i

scanf("%d %d",&a,&b);

mp[a][b]=1;

v[a].outdegree++;

v[b].indegree++;

}

测试输入情况

//for(i=1;i<=n;i++) printf("i=%d,in=%d,out=%d\n",i,v[i].indegree,v[i].outdegree);

//计算所有顶点的最早开始时间 可以先生成拓扑序列再做

//测试是否有环的那步有问题 会导致死循环好像 本题肯定无环 所以可以忽略

k=n;

memset(vis,0,sizeof(vis));

while(k>0){

for(i=1;i<=n;i++){

if(v[i].indegree==0 && vis[i]==0){

k--;

vis[i]=1;

for(j=1;j<=n;j++){

if(mp[i][j]==1 && vis[j]==0){

v[j].indegree--;

v[j].beg=max(v[j].beg,v[i].beg+v[i].cost);

if(v[j].beg+v[j].cost>late){//最晚完成的实验的时间

late=v[j].beg+v[j].cost;

t=j;

}

}

}

//break;

}

}

//if(i==n){//有环

//f=1;

//break;

//}

}

//计算所有顶点的最晚开始时间 可以先生成逆拓扑序列再做

for(i=1;i<=n;i++){

if(v[i].outdegree==0) v[i].end=late-v[i].cost;

}

k=n;

memset(vis,0,sizeof(vis));

while(k>0){

for(i=1;i<=n;i++){

if(v[i].outdegree==0 && vis[i]==0){

k--;

vis[i]=1;

for(j=1;j<=n;j++){

if(mp[j][i]==1 && vis[j]==0){

v[j].outdegree--;

v[j].end=min(v[j].end,v[i].end-v[j].cost);

}

}

}

//break;

}

//if(i==n) break;

}

if(f==0){

printf("%d\n",late);

for(i=1;i<=n;i++){

sum*=(v[i].end-v[i].beg+1);

sum%=mod;

}

printf("%ld",sum);

}

else printf("No solution, have cycle");

return 0;

}

标签:真题,int,开始,实验,复试,时间,完成,机试,define

来源: https://blog.csdn.net/weixin_49548350/article/details/114292252

Logo

汇聚原天河团队并行计算工程师、中科院计算所专家以及头部AI名企HPC专家,助力解决“卡脖子”问题

更多推荐