// Tarjan+缩点:找出入度为0的强连通分量,
//找出每个强连通分量的最小费用求和
#include<stdio.h> #include<stack> using namespace std; #define N 1002 int n,m,dfs[N],low[N],ins[N]; int in[N],belong[N],ct[N],cnt[N]; struct edge { int ed; struct edge *next; }*p[2*N]; void add(int x,int y) { edge *q=new edge; q->ed=y; q->next=p[x]; p[x]=q; } int ans,idx; stack<int>Q; void Tarjan(int x) { int v; dfs[x]=low[x]=idx++; Q.push(x); ins[x]=1; for( edge *j=p[x];j;j=j->next) { if(dfs[j->ed]==-1) { Tarjan(j->ed); low[x]=low[x]>low[j->ed]?low[j->ed]:low[x]; } else if(ins[j->ed]==1)//如果ed已经进栈 low[x]=low[x]>dfs[j->ed]?dfs[j->ed]:low[x]; } if(low[x]==dfs[x]) { ans++; while(1) { v=Q.top(); Q.pop(); ins[v]=0; belong[v]=ans;//缩点,一个强连通分量缩为一个点ans if(v==x)break; } } } int main() { int i,x,y; while(scanf("%d%d",&n,&m)!=EOF) { for(i=0;i<=n;i++) { p[i]=NULL; dfs[i]=-1; ins[i]=0; in[i]=0; ct[i]=111111111; } for(i=1;i<=n;i++) { scanf("%d",&cnt[i]); } for(i=0;i<m;i++) { scanf("%d%d",&x,&y); add(x,y); } ans=idx=0; for(i=1;i<=n;i++) if(dfs[i]==-1) Tarjan(i); for(i=1;i<=n;i++) { edge *q=p[i]; while(q) { if(belong[q->ed]!=belong[i]) { in[belong[q->ed]]++;//入度 } q=q->next; } if(ct[belong[i]]>cnt[i])ct[belong[i]]=cnt[i];//求每个缩后的点的最小费用 } int flag=0,k=0; for(i=1;i<=ans;i++) { if(in[i]==0) {flag+=ct[i];k++;} } printf("%d %d\n",k,flag); } return 0; }