//可作为模板,静态邻接表 //HDU1827 /* *State: HDU1827 125MS 336K 2082 B C++ *题目大意: * wiskey大牛要通过电话通知大家,如果你有别的队员的电话,就可以有你代劳 * 通知这些人,通知每个人的话费是不一样的,wiskey要花费最少达到通知所有 * 人的目的。打电话这种模型具有传递性,用<A, B>来表示A可以通知到B,即如果 * <A, B>,且<B, C>,则<A, C>。 *解题思路: * 强连通分量缩点,之后求入度为0的点的个数即为最小通知人数,求缩点后,每个 * 缩点的最小通知费用,再累加入度为0的缩点的费用即为最小费用。 */
View Code
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int MAXN = 1005; 7 const int MAXE = 2005; 8 int dfn[MAXN], low[MAXN], inS[MAXN]; 9 int step, scc, id[MAXN], myS[MAXN], top; 10 int weight[MAXN], head[MAXN], cntEdge; 11 12 typedef struct _node 13 { 14 int v, next; 15 }N; 16 N edge[MAXE]; 17 //缩点建有向无环图 18 int idw[MAXN]; 19 20 void addEdge(int u, int v) 21 { 22 edge[cntEdge].v = v; 23 edge[cntEdge].next = head[u]; 24 head[u] = cntEdge++; 25 } 26 27 void init() 28 { 29 cntEdge = top = 0; 30 scc = 1; 31 step = 0; 32 for(int i = 0; i < MAXN; i++) 33 { 34 idw[i] = 0; 35 id[i] = head[i] = -1; 36 inS[i] = 0; 37 dfn[i] = low[i] = -1; 38 } 39 } 40 41 void tarjan_scc(int n) 42 { 43 dfn[n] = low[n] = ++step; 44 myS[top++] = n; 45 inS[n] = 1; 46 for(int f = head[n]; f != -1; f = edge[f].next) 47 { 48 int son = edge[f].v; 49 if(dfn[son] == -1) 50 { 51 tarjan_scc(son); 52 low[n] = min(low[n], low[son]); 53 } 54 else if(inS[son] == 1) 55 low[n] = min(low[n], dfn[son]); 56 } 57 if(dfn[n] == low[n]) 58 { 59 int tmp, Min = INT_MAX; 60 do 61 { 62 tmp = myS[--top]; 63 id[tmp] = scc; 64 if(weight[tmp] < Min) 65 Min = weight[tmp]; 66 inS[tmp] = 0; 67 }while(top != 0 && tmp != n); 68 idw[scc] += Min; 69 scc++; 70 } 71 } 72 73 void deal_scc(int n, int &sol1, int &sol2) 74 { 75 int inTree[MAXN] = {0}; 76 for(int i = 1; i <= n; i++) 77 { 78 for(int j = head[i]; j != -1; j = edge[j].next) 79 { 80 int u = i, v = edge[j].v; 81 if(id[u] == id[v]) 82 continue; 83 else 84 inTree[id[v]]++; 85 } 86 } 87 sol1 = sol2 = 0; 88 for(int i = 1; i < scc; i++) 89 { 90 if(inTree[i] == 0) 91 { 92 sol1++; 93 sol2 += idw[i]; 94 } 95 } 96 97 } 98 99 int main(void) 100 { 101 #ifndef ONLINE_JUDGE 102 freopen("inHDU1827.txt", "r", stdin); 103 #endif 104 105 int n, m; 106 while(scanf("%d %d", &n, &m) == 2) 107 { 108 init(); 109 int u, v; 110 for(int i = 1; i <= n; i++) 111 scanf("%d", &weight[i]); 112 113 for(int i = 0; i < m; i++) 114 { 115 scanf("%d %d", &u, &v); 116 addEdge(u, v); 117 } 118 for(int i = 1; i <= n; i++) 119 { 120 if(dfn[i] == -1) 121 tarjan_scc(i); 122 } 123 int sol1, sol2; 124 deal_scc(n, sol1, sol2); 125 printf("%d %d\n", sol1, sol2); 126 } 127 return 0; 128 }