Bomb
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 1185 Accepted Submission(s): 401
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
题意:给你n个炸弹的坐标,爆炸半径和引爆需要的花费,问引爆所有炸弹需要的最少花费
解题思路:可以先建图后进行强联通缩点,然后重新建图后求出每个点引爆的最小花费,将所有入度为0的点需要引爆的最小花费进行求和
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include<cmath>
using namespace std;
#define LL long long
const int INF=0x3f3f3f3f;
const int N=1005;
int n;
struct Edge
{
int v,nt;
} edge[N*N];
struct node
{
int w;
LL x,y,r;
} x[N];
int s[N],cnt;
int dfn[N],low[N],id[N],dep,w[N];
bool vis[N],instack[N];
int res,graph[N][N],in[N];
stack<int>st;
void AddEdge(int u,int v)
{
edge[cnt].v=v;
edge[cnt].nt=s[u];
s[u]=cnt++;
}
void tarjan(int u)
{
st.push(u);
instack[u]=true;
vis[u]=true;
dfn[u]=low[u]=++dep;
for(int i=s[u]; ~i; i=edge[i].nt)
{
int v=edge[i].v;
if(!vis[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])
{
int t;
do
{
id[t=st.top()]=res;
st.pop();
instack[t]=false;
}
while(t!=u);
res++;
}
}
void solve()
{
res=0,dep=0;
while(!st.empty()) st.pop();
memset(vis,0,sizeof vis);
memset(instack,0,sizeof instack);
for(int i=1; i<=n; i++)
if(!vis[i]) tarjan(i);
memset(graph,0,sizeof graph);
memset(in,0,sizeof in);
for(int i=1; i<=n; i++)
for(int j=s[i]; ~j; j=edge[j].nt)
{
int v=edge[j].v;
if(id[i]!=id[v]) graph[id[i]][id[v]]=1,in[id[v]]++;
}
memset(w,INF,sizeof w);
for(int i=1; i<=n; i++)
w[id[i]]=min(w[id[i]],x[i].w);
int ans=0;
for(int i=0; i<res; i++)
if(!in[i])ans+=w[i];
printf("%d\n",ans);
}
int main()
{
int t,cas=0;
scanf("%d",&t);
while(t--)
{
memset(s,-1,sizeof s);
scanf("%d",&n);
cnt=1;
for(int i=1; i<=n; i++) scanf("%lld%lld%lld%d",&x[i].x,&x[i].y,&x[i].r,&x[i].w);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
if(i==j) continue;
if((x[i].x-x[j].x)*(x[i].x-x[j].x)+(x[i].y-x[j].y)*(x[i].y-x[j].y)<=x[i].r*x[i].r)
AddEdge(i,j);
}
printf("Case #%d: ",++cas);
solve();
}
return 0;
}