无论是思路还是写法我都觉得没问题啊!!!
#include<cstdio>
#include<iostream>
using namespace std;
const int maxn=1e7+5;
const int mod=1e9+7;
struct Edge{
int to,nxt;
};
Edge edge[maxn],e[maxn];
int head1[maxn],cnt1=0;
int head2[maxn],cnt2=0;
int z1[maxn],z2[maxn];
void add(int u,int v,int _){
if(_==1){
edge[++cnt1].to=v;
edge[cnt1].nxt=head1[u];
head1[u]=cnt1;
}
else{
e[++cnt2].to=v;
e[cnt2].nxt=head2[u];
head2[u]=cnt2;
}
}
int dfn[maxn],low[maxn],ts;
int stk[maxn],top;
bool instk[maxn];
int scc[maxn],sc;
int siz[maxn];
void tarjan(int u){
dfn[u]=low[u]=++ts;
stk[++top]=u;
instk[u]=true;
for(int i=head1[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(instk[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u]){
sc++;
while(true){
int x=stk[top--];;
scc[x]=sc;
siz[sc]++;
instk[x]=false;
if(x==u)break;
}
}
}
int ans,_ans=1;
int cnt[maxn];
int main(){
//输入
int n,m;
cin>>n;
int i;
for(i=1;i<=n;i++)cin>>z1[i];
cin>>m;
int a,b;
//加边
for(i=0;i<m;i++){
scanf("%d%d",&a,&b);
add(a,b,1);
}
//分出强连通分量
for(i=1;i<=n;i++){
if(!dfn[i])tarjan(i);
}
//缩点
for(i=1;i<=sc;i++)z2[i]=0x3f3f3f3f;
for(int u=1;u<=n;u++){
for(i=head1[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(scc[u]!=scc[v])add(scc[u],scc[v],21541);//1~sc
}
z2[scc[u]]=min(z2[scc[u]],z1[u]);//点权
}
//算每个强连通分量内最小价格的个数
for(int u=1;u<=n;u++){
if(z2[scc[u]]==z1[u])cnt[scc[u]]++;
}
//处理答案
for(i=1;i<=sc;i++){
ans+=z2[i];//最少价格
_ans*=cnt[i];//乘法原理
_ans%=mod;
}
printf("%d %d",ans,_ans);
return 0;
}