Bomb
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 725 Accepted Submission(s): 260
Problem Description
There are
N
bombs needing exploding.
Each bomb has three attributes: exploding radius ri , position (xi,yi) and lighting-cost ci which means you need to pay ci cost making it explode.
If a un-lighting bomb is in or on the border the exploding area of another exploding one, the un-lighting bomb also will explode.
Now you know the attributes of all bombs, please use the minimum cost to explode all bombs.
Each bomb has three attributes: exploding radius ri , position (xi,yi) and lighting-cost ci which means you need to pay ci cost making it explode.
If a un-lighting bomb is in or on the border the exploding area of another exploding one, the un-lighting bomb also will explode.
Now you know the attributes of all bombs, please use the minimum cost to explode all bombs.
Input
First line contains an integer
T
, which indicates the number of test cases.
Every test case begins with an integers N , which indicates the numbers of bombs.
In the following N lines, the ith line contains four intergers xi , yi , ri and ci , indicating the coordinate of ith bomb is (xi,yi) , exploding radius is ri and lighting-cost is ci .
Limits
- 1≤T≤20
- 1≤N≤1000
- −108≤xi,yi,ri≤108
- 1≤ci≤104
Every test case begins with an integers N , which indicates the numbers of bombs.
In the following N lines, the ith line contains four intergers xi , yi , ri and ci , indicating the coordinate of ith bomb is (xi,yi) , exploding radius is ri and lighting-cost is ci .
Limits
- 1≤T≤20
- 1≤N≤1000
- −108≤xi,yi,ri≤108
- 1≤ci≤104
Output
For every test case, you should output
'Case #x: y', where
x indicates the case number and counts from
1 and
y is the minimum cost.
Sample Input
1 5 0 0 1 5 1 1 1 6 0 1 1 7 3 0 2 10 5 0 1 4
Sample Output
Case #1: 15
Source
Recommend
/*
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5934
题目大意:
给你N个炸弹,对应已知其坐标和爆炸范围,以及引爆这个炸弹需要的花费,
对应如果引爆了炸弹a,没有引爆炸弹b,但是b炸弹在a炸弹的作用范围之内,
那么b炸弹也会被引爆,问将所有炸弹都引爆需要的最小花费。
首先O(n^2)预处理哪些炸弹可以被哪些炸弹引爆,得到一个有向图。
强连通缩点
缩点时顺便找出当前这个连通集合里的所需花费最小的那个炸弹
*/
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <cmath>
#include <string>
#include <sstream>
#include <map>
#include <set>
#define pi acos(-1.0)
#define LL long long
#define ULL unsigned long long
#define inf 0x3f3f3f3f
#define INF 1e18
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
typedef pair<int, int> P;
const double eps = 1e-10;
const int maxn = 1e6 + 5;
const int N = 1e3 + 5;
const int mod = 1e8;
int stack[N], instack[N];
int belong[N];
int low[N], dfn[N];
int in[N], out[N];
int cnt, top, index, n;
vector<int> G[N];
LL waste[N], cas = 1;
struct Point{
LL x, y, r, cost;
}p[N];
void init()
{
memset(low, 0, sizeof(low));
memset(dfn, 0, sizeof(dfn));
memset(in, 0, sizeof(in));
memset(out, 0, sizeof(out));
memset(instack, 0, sizeof(instack));
cnt = top = index = 0;
for(int i = 1; i <= n; i++)
G[i].clear();
}
void Tarjan(int u)
{
stack[++top] = u;
low[u] = dfn[u] = ++index;
instack[u] = 1;
for (int i = 0; i < G[u].size(); i++){
int v = G[u][i];
if (!dfn[v]){
Tarjan(v);
low[u] = min(low[u], low[v]);
}
else if (instack[v])
low[u] = min(low[u], dfn[v]);
}
if (dfn[u] == low[u]){
++cnt;
LL cost = INF;
while (1){
int v = stack[top--];
instack[v] = 0;
belong[v] = cnt;
cost = min(cost, p[v].cost); // 找出这个连通集合里的所需花费最小的炸弹
if (v == u) break;
}
waste[cnt] = cost;
}
}
void solve()
{
int i, j, v;
for (i = 1; i <= n; i++){
for (j = 0; j < G[i].size(); j++){
v = G[i][j];
if (belong[i] != belong[v]){ // 两点之间有边,但不是属于一个强联通分量的边
out[belong[i]]++; // 缩点后的点出度+1
in[belong[v]]++; // 缩点后的点入度+1
}
}
}
if (cnt == 1){
printf("Case #%I64d: %I64d\n", cas++, waste[cnt]);
}
else {
LL sum = 0;
for (i = 1; i <= cnt; i++){
if (in[i] == 0) // 入度为0 说明至少要点爆一个这个集合里的炸弹
sum += waste[i]; // 点那个之前找出来的花费最小的
}
printf("Case #%I64d: %I64d\n", cas++, sum);
}
}
LL dist(int i, int j)
{
LL x = p[i].x - p[j].x;
LL y = p[i].y - p[j].y;
return (x*x + y*y);
}
int main(void)
{
// freopen("in.txt","r", stdin);
int T;
cin >> T;
while (T--)
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%I64d %I64d %I64d %I64d", &p[i].x, &p[i].y, &p[i].r, &p[i].cost);
init();
for (int i = 1; i <= n; i++){
for (int j = 1; j <= n; j++){
if (i == j) continue;
if (dist(i, j) <= p[i].r*p[i].r)
G[i].push_back(j);
}
}
for (int i = 1; i <= n; i++)
if (!dfn[i])
Tarjan(i);
solve();
}
return 0;
}