残忍的题面
我们来看这一道题,其实冗长的题目告诉我们一个核心——用tarjan
tarjan是用来干什么呢?是用来求强连通分量(代码中指sc)
求出来又有什么用呢?每当我们求出一个强连通分量时,就去计算当前强连通分量中各点最小值是多少以及其个数
然后分别开两个计数器,假设ans1是用来存个数相乘,ans2是用来累加最小值的。
临门一脚,千万别忘了取% 另外注意如果小伙伴这样和我一样写tarjan的话
for(int i=head[x];i!=-1;i=e[i].next)
一定记住,在main函数里要
memset(head,-1,sizeof(head));
(看本蒟蒻的代码,大神勿喷)
#include<bits/stdc++.h> using namespace std; const int mod = 1e9+7; #define ll long long #define inf 1e9 const int N = 310000; const int M = 210000; int head[M],v[M],dfn[M],low[M],q[M]; int be[M],sum[M],hh[M],num[M]; int ss,n,m,now,cnt,tot,sc; ll ans1=1,ans2; bool f[N]; struct Edge{ int to,next; }e[N]; void add(int x,int y) { e[++ss].to=y; e[ss].next=head[x]; head[x]=ss; } void dfs(int x)//这里的dfs和下面tarjan分着写的,不管怎样都是tarjan模板 { low[x]=dfn[x]=++cnt; q[++tot]=x; f[x]=1; for(int i=head[x];i!=-1;i=e[i].next) { if(!dfn[e[i].to]) { dfs(e[i].to); low[x]=min(low[x],low[e[i].to]); } else if(f[e[i].to]) low[x]=min(low[x],dfn[e[i].to]); } if(low[x]==dfn[x]) { sc++; be[x]=sc; hh[sc]=inf; do { now=q[tot--]; f[now]=0; be[now]=sc; if(v[now]<hh[sc]) { hh[sc]=v[now]; num[sc]=0; } if(v[now]==hh[sc]) num[sc]++; } while(now!=x); } } void tarjan() { for(int i=1;i<=n;i++) if(!dfn[i]) dfs(i); } int main() { memset(head,-1,sizeof(head)); cin>>n; for(int i=1;i<=n;i++) cin>>v[i]; cin>>m; for(int i=1;i<=m;i++) { int x,y; cin>>x>>y; add(x,y); } tarjan(); for(int i=1;i<=sc;i++)//最后的处理,ans1别忘初值为1 { ans1*=num[i]; ans2+=hh[i]; ans1%=mod; } cout<<ans2<<" "<<ans1; return 0; }