1 /****************************************************
  2 
  3     Summer Holiday(hdu 1827)
  4     http://acm.hdu.edu.cn/showproblem.php?pid=1827
  5     强连通
  6     先通过tarjan找出强连通分量,强连通分量入度为零
  7     的就一定要打电话,所以入度为零就是最少要打的电
  8     话数,然后对每个强连通分量找最小值就是最少话费
  9     
 10 ****************************************************/
 11 
 12 #include<cstdio>
 13 #include<cstring>
 14 #include<algorithm>
 15 #include<vector>
 16 #include<stack>
 17 using namespace std;
 18 
 19 const int mx=1005;
 20 vector<int>g[mx];
 21 stack<int>s;
 22 int dfn[mx],low[mx];
 23 int vs[mx],sccno[mx];
 24 int a[mx],ans[mx],in[mx];
 25 int dfs_cut,scc_cut;
 26 
 27 void Init(int n)
 28 {
 29     dfs_cut=scc_cut=0;
 30     memset(dfn,0,sizeof(dfn));
 31     memset(low,0,sizeof(low));
 32     memset(vs,0,sizeof(vs));
 33     memset(in,0,sizeof(in));
 34     memset(ans,0,sizeof(ans));
 35     memset(sccno,0,sizeof(sccno));
 36     for (int i=1;i<=n;i++) g[i].clear();
 37     while (!s.empty()) s.pop();
 38 }
 39 
 40 
 41 void dfs(int u)
 42 {
 43     vs[u]=1;
 44     s.push(u);
 45     low[u]=dfn[u]=++dfs_cut;
 46     for (int i=0;i<g[u].size();i++)
 47     {
 48         int v=g[u][i];
 49         if (!vs[v])
 50         {
 51             dfs(v);
 52             low[u]=min(low[u],low[v]);
 53         }
 54         else if (!sccno[v]) low[u]=min(low[u],dfn[v]);
 55     }
 56     if (low[u]==dfn[u])
 57     {
 58         scc_cut++;
 59         while(1)
 60         {
 61             int x=s.top();
 62             s.pop();
 63             sccno[x]=scc_cut;
 64             if (x==u) break;
 65         }
 66     }
 67 }
 68 
 69 
 70 int main()
 71 {
 72     int n,m,i,j;
 73     while (~scanf("%d%d",&n,&m))
 74     {
 75         Init(n);
 76         for (i=1;i<=n;i++) scanf("%d",&a[i]);
 77         int u,v;
 78         while(m--)
 79         {
 80             scanf("%d%d",&u,&v);
 81             g[u].push_back(v);
 82         }
 83 
 84         for (i=1;i<=n;i++)
 85         {
 86             if (!vs[i]) dfs(i);
 87         }
 88         for (i=1;i<=n;i++)
 89         {
 90             for (j=0;j<g[i].size();j++)
 91             {
 92                 int v=g[i][j];
 93                 if (sccno[i]!=sccno[v]) in[sccno[v]]=1;
 94             }
 95         }
 96         for (i=1;i<=n;i++)
 97         {
 98             if (!in[sccno[i]])
 99             {
100                 if (!ans[sccno[i]]) ans[sccno[i]]=a[i];
101                 else ans[sccno[i]]=min(ans[sccno[i]],a[i]);
102             }
103         }
104         int ans1=0,cut=0;
105         for (i=1;i<=scc_cut;i++)
106         {
107             ans1+=ans[i];
108             if (ans[i]) cut++;
109         }
110         printf("%d %d\n",cut,ans1);
111     }
112 }

 

posted on 2016-04-26 21:15  pb2016  阅读(231)  评论(0编辑  收藏  举报