题意&& 思路 :求每个强联通中 , cost 最小的数,以及最小值出现的次数 . 用mmin维护最小值,再开个数组维护当前这个强联通,对应每一个值的出现次数.
#include<bits/stdc++.h>
#define bug cout <<"bug"<<endl;
using namespace std;
typedef long long ll;
const int MAX_N=1e5+5;
const int MOD=1e9+7;
const int INF=0x3f3f3f3f;
vector <int> edge[MAX_N];
map<int,int> scc[MAX_N];
map<int,int> mn;
int n,m,cur,cnt,top,s[MAX_N],DFN[MAX_N],LOW[MAX_N],w[MAX_N],mp[MAX_N];
void tarjan(int u){
DFN[u]=LOW[u]=++cur;
s[++top]=u;
for(int i=0;i<(int)edge[u].size();i++){
int v=edge[u][i];
if(!DFN[v]){
tarjan(v);
LOW[u]=min(LOW[u],LOW[v]);
}
else if(DFN[v] && !mp[v]) LOW[u]=min(LOW[u],DFN[v]);
}
if(DFN[u]==LOW[u]){
int v=-1;
cnt++;
int mmin=INF;
while(u!=v){
v=s[top--];
scc[cnt][w[v]]++;
mmin=min(mmin,w[v]);
mp[v]=cnt;
}
mn[cnt]=mmin;
}
}
int main(void){
cin >> n;
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
cin >> m;
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
edge[u].push_back(v);
}
for(int i=1;i<=n;i++)
if(!DFN[i]) tarjan(i);
ll sum=0,ans=1;
for(int i=1;i<=cnt;i++){
int m=mn[i];
int c=scc[i][m];
sum+=m;
ans=(ans*c)%MOD;
}
cout << sum <<" "<<ans<<endl;
return 0;
}