题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5934
题意:有n个炸弹,爆炸范围和点燃花费给你,如果一个爆炸那么它爆炸范围内的炸弹也会爆炸。问让所有炸弹爆炸的最小花费。
遍历任意两个炸弹,如果i在j的爆炸范围内,则建一条有向边。缩完点以后找入度为0的点点燃就行了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 typedef struct Edge { 6 int u; 7 int v; 8 int next; 9 Edge() { next = -1; } 10 }Edge; 11 typedef struct P { 12 LL x, y, r; 13 int c; 14 }P; 15 const int maxn = 1510; 16 P p[maxn]; 17 18 int head[maxn], ecnt; 19 Edge edge[maxn*maxn]; 20 int n, m; 21 22 int bcnt, dindex; 23 int dfn[maxn], low[maxn]; 24 int stk[maxn], top; 25 int belong[maxn]; 26 bool instk[maxn]; 27 int ret[maxn]; 28 int in[maxn]; 29 30 void init() { 31 memset(edge, 0, sizeof(edge)); 32 memset(head, -1, sizeof(head)); 33 memset(instk, 0, sizeof(instk)); 34 memset(dfn, 0, sizeof(dfn)); 35 memset(low, 0, sizeof(low)); 36 memset(belong, 0, sizeof(belong)); 37 ecnt = top = bcnt = dindex = 0; 38 } 39 40 void adde(int uu, int vv) { 41 edge[ecnt].u = uu; 42 edge[ecnt].v = vv; 43 edge[ecnt].next = head[uu]; 44 head[uu] = ecnt++; 45 } 46 47 void tarjan(int u) { 48 int v = u; 49 dfn[u] = low[u] = ++dindex; 50 stk[++top] = u; 51 instk[u] = 1; 52 for(int i = head[u]; ~i; i=edge[i].next) { 53 v = edge[i].v; 54 if(!dfn[v]) { 55 tarjan(v); 56 low[u] = min(low[u], low[v]); 57 } 58 else if(instk[v]) low[u] = min(low[u], dfn[v]); 59 } 60 if(dfn[u] == low[u]) { 61 bcnt++; 62 do { 63 v = stk[top--]; 64 instk[v] = 0; 65 belong[v] = bcnt; 66 } while(v != u); 67 } 68 } 69 70 LL dis(P a, P b) { 71 LL l1 = a.x - b.x; 72 LL l2 = a.y - b.y; 73 return l1 * l1 + l2 * l2; 74 } 75 76 int main() { 77 // freopen("in", "r", stdin); 78 int T, _ = 1; 79 scanf("%d", &T); 80 while(T--) { 81 scanf("%d", &n); 82 init(); 83 memset(in, 0, sizeof(in)); 84 for(int i = 1; i <= n; i++) ret[i] = 10000000; 85 for(int i = 1; i <= n; i++) { 86 scanf("%I64d%I64d%I64d%d",&p[i].x,&p[i].y,&p[i].r,&p[i].c); 87 } 88 for(int i = 1; i <= n; i++) { 89 for(int j = 1; j <= n; j++) { 90 if(i == j) continue; 91 LL d = dis(p[i], p[j]); 92 if(d <= (LL)p[i].r * p[i].r) adde(i, j); 93 } 94 } 95 for(int i = 1; i <= n; i++) { 96 if(!dfn[i]) tarjan(i); 97 } 98 for(int i = 0; i < ecnt; i++) { 99 int u = edge[i].u, v = edge[i].v; 100 if(belong[u] != belong[v]) in[belong[v]]++; 101 } 102 for(int i = 1; i <= n; i++) { 103 ret[belong[i]] = min(ret[belong[i]], p[i].c); 104 } 105 int tot = 0; 106 for(int i = 1; i <= bcnt; i++) { 107 if(!in[i]) tot += ret[i]; 108 } 109 printf("Case #%d: ", _++); 110 printf("%d\n", tot); 111 } 112 return 0; 113 }
时间: 2024-10-19 08:56:04