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 }