http://acm.hdu.edu.cn/showproblem.php?pid=5934
题意:有N个炸弹,每个炸弹有一个坐标,一个爆炸范围和一个爆炸花费,如果一个炸弹的爆炸范围内有另外的炸弹,那么如果该炸弹爆炸,就会引爆所有爆炸范围内的炸弹,求让所有炸弹爆炸的最小花费。
思路:重现的时候来不及做。先n^2的把每个炸弹爆炸范围内的炸弹都连一条有向边,然后再找强连通分量缩点,这样会形成多个DAG,然后对于每个DAG找一个入度为0的点,找这个入度为0的点里面耗费最小的去引爆,就可以了。
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <string> 7 #include <iostream> 8 #include <stack> 9 #include <map> 10 #include <queue> 11 using namespace std; 12 #define N 1010 13 #define INF 0x7fffffff 14 struct node 15 { 16 int u, v, nxt; 17 }edge[2000010]; 18 struct P 19 { 20 long long x, y, r, c; 21 }p[N]; 22 int belong[N], vis[N], head[N], tot, cnt, num, dfn[N], low[N], in[N], out[N]; 23 stack<int> sta; 24 25 void init() { 26 tot = cnt = num = 0; 27 memset(dfn, 0, sizeof(dfn)); 28 memset(belong, 0, sizeof(belong)); 29 memset(vis, 0, sizeof(vis)); 30 memset(head, -1, sizeof(head)); 31 memset(in, 0, sizeof(in)); 32 memset(out, 0, sizeof(out)); 33 while(sta.size()) sta.pop(); 34 } 35 36 void add(int u, int v) { 37 edge[tot].u = u; edge[tot].v = v; edge[tot].nxt = head[u]; head[u] = tot++; 38 } 39 40 bool dis(int u, int v) { 41 double a = sqrt(((p[u].x - p[v].x) * (p[u].x - p[v].x) + (p[u].y - p[v].y) * (p[u].y - p[v].y)) * 1.0); 42 if(a <= p[u].r) return true; 43 return false; 44 } 45 46 void tarjan(int u) { 47 vis[u] = 1; 48 sta.push(u); 49 dfn[u] = low[u] = ++cnt; 50 for(int i = head[u]; ~i; i = edge[i].nxt) { 51 int v = edge[i].v; 52 if(!dfn[v]) { 53 tarjan(v); 54 if(low[v] < low[u]) low[u] = low[v]; 55 } else if(vis[v]) { 56 if(dfn[v] < low[u]) low[u] = dfn[v]; 57 } 58 } 59 if(dfn[u] == low[u]) { 60 ++num; 61 while(true) { 62 int v = sta.top(); sta.pop(); 63 belong[v] = num; vis[v] = 0; 64 if(v == u) break; 65 } 66 } 67 } 68 69 int main() 70 { 71 int t, cas = 1; 72 scanf("%d", &t); 73 while(t--) { 74 int n; 75 scanf("%d", &n); 76 init(); 77 for(int i = 1; i <= n; i++) scanf("%I64d%I64d%I64d%I64d", &p[i].x, &p[i].y, &p[i].r, &p[i].c); 78 for(int i = 1; i <= n; i++) { 79 for(int j = 1; j <= n; j++) { 80 if(i == j) continue; 81 if(dis(i, j)) add(i, j); 82 } 83 } 84 for(int i = 1; i <= n; i++) if(!dfn[i]) tarjan(i); 85 for(int u = 1; u <= n; u++) { 86 for(int i = head[u]; ~i; i = edge[i].nxt) { 87 int v = edge[i].v; 88 if(belong[u] != belong[v]) { 89 out[belong[u]]++; 90 in[belong[v]]++; 91 } 92 } 93 } 94 long long ans = 0; 95 for(int i = 1; i <= num; i++) { 96 if(in[i] == 0) { 97 int mi = INF; 98 for(int j = 1; j <= n; j++) { 99 if(belong[j] == i) { 100 if(p[j].c < mi) mi = p[j].c; 101 } 102 } 103 ans += mi; 104 } 105 } 106 printf("Case #%d: %d ", cas++, ans); 107 } 108 return 0; 109 }