HDOJ1827解题报告【tarjian强连通分量】
题目地址:
http://acm.hdu.edu.cn/showproblem.php?pid=1827
题目概述:
中文题就略了。
大致思路:
先求出整个图的强连通分量然后缩点,两个scc如果相连则只需要通知一个就好了,统计所有入度为0的scc个数即为最少数量,通知这些scc的最小花费即为答案所求。
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <ctime> 7 #include <map> 8 #include <stack> 9 #include <queue> 10 #include <cstring> 11 #include <algorithm> 12 using namespace std; 13 14 #define sacnf scanf 15 #define scnaf scanf 16 #define maxn 1010 17 #define maxm 26 18 #define inf 1061109567 19 #define Eps 0.00001 20 const double PI=acos(-1.0); 21 #define mod 7 22 #define MAXNUM 10000 23 void Swap(int &a,int &b) {int t=a;a=b;b=t;} 24 int Abs(int x) {return (x<0)?-x:x;} 25 typedef long long ll; 26 typedef unsigned int uint; 27 28 vector<int> G[maxn]; 29 stack<int> S; 30 31 int pre[maxn],low[maxn],scc[maxn]; 32 int scc_cnt,dfs_clock; 33 int n,m; 34 int cost[maxn],ans[maxn],in[maxn]; 35 36 void dfs(int u) 37 { 38 pre[u]=low[u]=++dfs_clock; 39 S.push(u); 40 int len=G[u].size(); 41 for(int i=0;i<len;i++) 42 { 43 int v=G[u][i]; 44 if(!pre[v]) 45 { 46 dfs(v); 47 low[u]=min(low[u],low[v]); 48 } 49 else if(!scc[v]) low[u]=min(low[u],pre[v]); 50 } 51 if(pre[u]==low[u]) 52 { 53 scc_cnt++; 54 for(;;) 55 { 56 int t=S.top();S.pop(); 57 scc[t]=scc_cnt; 58 if(t==u) break; 59 } 60 } 61 } 62 63 void find_scc() 64 { 65 memset(pre,0,sizeof(pre)); 66 memset(low,0,sizeof(low)); 67 memset(scc,0,sizeof(scc)); 68 scc_cnt=0;dfs_clock=0; 69 for(int i=1;i<=n;i++) 70 if(!pre[i]) dfs(i); 71 } 72 73 int main() 74 { 75 //freopen("data.in","r",stdin); 76 //freopen("data.out","w",stdout); 77 //clock_t st=clock(); 78 while(~scanf("%d%d",&n,&m)) 79 { 80 int a,b; 81 for(int i=1;i<=n;i++) 82 { 83 G[i].clear();scanf("%d",&cost[i]); 84 } 85 for(int i=1;i<=m;i++) 86 { 87 scanf("%d%d",&a,&b); 88 G[a].push_back(b); 89 } 90 find_scc(); 91 for(int i=1;i<=scc_cnt;i++) ans[i]=inf,in[i]=0; 92 for(int i=1;i<=n;i++) 93 ans[scc[i]]=min(ans[scc[i]],cost[i]); 94 for(int i=1;i<=n;i++) 95 { 96 int len=G[i].size(); 97 for(int k=0;k<len;k++) 98 { 99 int j=G[i][k]; 100 if(scc[i]!=scc[j]) in[scc[j]]++; 101 } 102 } 103 int cnt=0,sum=0; 104 for(int i=1;i<=scc_cnt;i++) 105 { 106 if(in[i]==0) cnt++,sum+=ans[i]; 107 } 108 printf("%d %d\n",cnt,sum); 109 } 110 //clock_t ed=clock(); 111 //printf("\n\nTime Used : %.5lf Ms.\n",(double)(ed-st)/CLOCKS_PER_SEC); 112 return 0; 113 }