标签:
http://acm.hdu.edu.cn/showproblem.php?pid=1827
思路:强连通分量缩点后找入度为0的点,然后对于属于该强连通分量的找一个最小耗费的入口。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <queue> 6 #include <cmath> 7 #include <map> 8 #include <vector> 9 #include <stack> 10 using namespace std; 11 #define N 80010 12 #define M 30010 13 #define INF 0x3f3f3f3f 14 struct node 15 { 16 int u, v, next; 17 }edge[N*2]; 18 stack<int> sta; 19 int tot, cnt, num, head[N], belong[N], dfn[N], low[N], n, m, a[N], in[N], mi[N]; 20 bool vis[N]; 21 22 void init() 23 { 24 tot = cnt = num = 0; 25 while(sta.size()) sta.pop(); 26 memset(head, -1, sizeof(head)); 27 memset(belong, 0, sizeof(belong)); 28 memset(dfn, 0, sizeof(dfn)); 29 memset(low, 0, sizeof(low)); 30 memset(vis, false, sizeof(vis)); 31 memset(in, 0, sizeof(in)); 32 memset(mi, INF, sizeof(mi)); 33 } 34 35 void add(int u, int v) 36 { 37 edge[tot].u = u; edge[tot].v = v; edge[tot].next = head[u]; head[u] = tot++; 38 } 39 40 void tarjan(int u) 41 { 42 vis[u] = 1; 43 sta.push(u); 44 dfn[u] = low[u] = ++cnt; 45 for(int i = head[u]; ~i; i = edge[i].next) { 46 int v = edge[i].v; 47 if(!dfn[v]) { 48 tarjan(v); 49 if(low[v] < low[u]) low[u] = low[v]; 50 } else if(vis[v]) { 51 if(dfn[v] < low[u]) low[u] = dfn[v]; 52 } 53 } 54 if(dfn[u] == low[u]) { 55 ++num; 56 int top = -1; 57 while(top != u) { 58 top = sta.top(); sta.pop(); 59 belong[top] = num; 60 vis[top] = 0; 61 } 62 } 63 } 64 65 int main() 66 { 67 while(~scanf("%d%d", &n, &m)) { 68 init(); 69 for(int i = 1; i <= n; i++) scanf("%d", &a[i]); 70 for(int i = 0; i < m; i++) { 71 int u, v; 72 scanf("%d%d", &u, &v); 73 add(u, v); 74 } 75 for(int i = 1; i <= n; i++) 76 if(!dfn[i]) tarjan(i); 77 for(int u = 1; u <= n; u++) { 78 for(int i = head[u]; ~i; i = edge[i].next) { 79 int v = edge[i].v; 80 if(belong[u] != belong[v]) { //缩点后找入度为0的点 81 in[belong[v]]++; 82 } 83 } 84 } 85 int ans = 0, sum = 0; 86 for(int i = 1; i <= num; i++) { 87 if(!in[i]) { 88 ans++; 89 for(int j = 1; j <= n; j++) { 90 if(belong[j] == i) { 91 if(a[j] < mi[i]) { 92 mi[i] = a[j]; //对于不同的强连通分量之间找耗费最小的入口 93 } 94 } 95 } 96 sum += mi[i]; 97 } 98 } 99 printf("%d %d\n", ans, sum); 100 } 101 return 0; 102 } 103 104 /* 105 4 3 106 1 2 3 4 107 1 2 108 1 3 109 1 4 110 */
标签:
原文地址:http://www.cnblogs.com/fightfordream/p/5929270.html