Problem Description
There are
N
bombs needing exploding.
Each bomb has three attributes: exploding radius r
i![]()
, position
(x
i
,y
i
)
and lighting-cost
c
i![]()
which means you need to pay
c
i![]()
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 r
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
x
i![]()
,
y
i![]()
,
r
i![]()
and
c
i![]()
, indicating the coordinate of ith bomb is
(x
i
,y
i
)
, exploding radius is
r
i![]()
and lighting-cost is
c
i![]()
.
Limits
- 1≤T≤20
- 1≤N≤1000
- −10
8
≤x
i
,y
i
,r
i
≤10
8![]()
- 1≤c
i
≤10
4![]()
Every test case begins with an integers N
In the following N
Limits
- 1≤T≤20
- 1≤N≤1000
- −10
- 1≤c
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对图进行强联通后缩点寻找入度为0的点,在入度为0的联通快中寻找价值最小的的点值即为该强连通分量的值;
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mms(x, y) memset(x, y, sizeof x)
const int MAX = 1500;
const int INF = 0x3f3f3f3f;
struct node
{
ll x, y, r;
int c;
} a[MAX];
struct edge
{
int to, next;
} e[MAX * MAX * 2];
int num, cnt, pos, sig, n;
bool vis[MAX];
int ans[MAX];
int dfn[MAX];
int low[MAX];
int in[MAX];
int head[MAX];
int col[MAX];
int Stack[MAX];
void add(int u, int v)
{
e[num] = {v, head[u]};
head[u] = num++;
}
void init()
{
mms(ans, INF);
mms(vis, 0);
mms(low, 0);
mms(dfn, 0);
mms(in, 0);
mms(col, 0);
mms(Stack, 0);
cnt = pos = sig = 0;
}
void tarjan(int u)
{
int v;
low[u] = dfn[u] = ++cnt;
Stack[pos++] = u;
vis[u] = 1;
for(int i = head[u]; i != -1; i = e[i].next)
{
v = e[i].to;
if(!dfn[v])
{
tarjan(v);
if(low[u] > low[v])
low[u] = low[v];
}
else if(vis[v] && low[u] > dfn[v])
low[u] = dfn[v];
}
if(low[u] == dfn[u])
{
sig++;
do
{
v = Stack[--pos];
vis[v] = 0;
col[v] = sig;
}
while(u != v);
}
}
int main()
{
int N, kase = 0;
scanf("%d", &N);
while(N--)
{
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%lld%lld%lld%lld", &a[i].x, &a[i].y, &a[i].r, &a[i].c);
num = 0;
mms(head, -1);
for(int i = 1; i <= n; i++)
{
for(int j = i + 1; j <= n; j++)
{
ll x = a[i].x - a[j].x;
ll y = a[i].y - a[j].y;
ll dis = x * x + y * y;
ll dis1 = a[i].r * a[i].r;
ll dis2 = a[j].r * a[j].r;
if(dis <= dis1)
add(i, j);
if(dis <= dis2)
add(j, i);
}
}
init();
for(int i = 1; i <= n; i++)
if(!dfn[i])
tarjan(i);
for(int i = 1; i <= n; i++)
{
for(int j = head[i]; j != -1; j = e[j].next)
{
int x = e[j].to;
if(col[i] != col[x])
in[col[x]]++;
}
}
for(int i = 1; i <= n; i++)
{
int x = col[i];
if(in[x] == 0)
ans[x] = min(ans[x], a[i].c);
}
int res = 0;
for(int i = 1; i <= sig; i++)
if(in[i] == 0)
res += ans[i];
printf("Case #%d: %d\n", ++kase, res);
}
return 0;
}