hdu 1827

强连通分量——tarjin算法;

这题的思路就是找出多少个出度为0的连通分量,结果就是这些连通分量的元素的最小值相加;

一道很简单的题,改了我好久,= =!~

贴代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<stack>
 5 #include<vector>
 6 #define maxn 1005
 7 using namespace std;
 8 
 9 int dfn[maxn],low[maxn],pen[maxn],b[maxn];
10 int nncount,ans,cc[maxn],cnt,in[maxn];
11 bool instack[maxn];
12 vector<int>ve[maxn];
13 stack<int>s;
14 
15 void tarjin(int x)
16 {
17     dfn[x]=low[x]=++nncount;
18     instack[x]=1;
19     s.push(x);
20     int l=ve[x].size();
21     for(int i=0; i<l; i++)
22     {
23         int v=ve[x][i];
24         if(!dfn[v])
25         {
26             tarjin(v);
27             low[x]=min(low[v],low[x]);
28         }
29         else if(instack[v])
30             low[x]=min(low[x],dfn[v]);
31     }
32     if(dfn[x]==low[x])
33     {
34         cnt++;
35         int t;
36         do
37         {
38             t=s.top();
39             s.pop();
40             b[t]=cnt;
41             instack[t]=0;
42         }
43         while(t!=x);
44     }
45 }
46 
47 int main()
48 {
49     int n,m,x,y,sum;
50     while(scanf("%d%d",&n,&m)!=EOF)
51     {
52         memset(low,0,sizeof low);
53         memset(b,0,sizeof b);
54         memset(dfn,0,sizeof dfn);
55         memset(in,0,sizeof in);
56         memset(cc,0,sizeof cc);
57         memset(instack,0,sizeof instack);
58         nncount=ans=sum=cnt=0;
59         for(int i=1; i<=n; i++)
60         {
61             scanf("%d",&pen[i]);
62             ve[i].clear();
63         }
64         while(!s.empty()) s.pop();
65         for(int i=0; i<m; i++)
66         {
67             scanf("%d%d",&x,&y);
68             ve[x].push_back(y);
69         }
70         for(int i=1; i<=n; i++)
71             if(!dfn[i])
72                 tarjin(i);
73         for(int i=1; i<=n; i++)
74         {
75             int l=ve[i].size();
76             for(int j=0; j<l; j++)
77             {
78                 int v=ve[i][j];
79                 if(b[i]!=b[v]) in[b[v]]++;
80             }
81         }
82         for(int i=1; i<=cnt; i++)
83         {
84             if(in[i]==0)ans++;
85             cc[i]=999999;
86         }
87         for(int i=1; i<=n; i++)
88         {
89             int v=b[i];
90             if(in[v]==0) cc[v]=min(cc[v],pen[i]);
91         }
92         for(int i=1; i<=cnt; i++)
93             if(cc[i]!=999999)
94                 sum+=cc[i];
95         printf("%d %d\n",ans,sum);
96     }
97     return 0;
98 }
View Code

 

posted @ 2013-09-04 20:08  Yours1103  阅读(150)  评论(0编辑  收藏  举报