Bomb
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 46 Accepted Submission(s): 22
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
题意:二维平面上有 n 个炸弹,每个炸弹有个引爆的代价和爆炸半径,问至少花费多少代价才能引爆所有炸弹。炸弹爆炸的时候会引爆半径及内所有炸弹。
解:构造,将一个炸弹引爆另一条边的过程变成一条有向边。炸弹就是点。所以,那些入度为0的点就是必须要引爆的点(无炸弹将其引爆)。由此构图,强连通分量缩点,使得整张图无连通,求出所有入度为0的权值即可(一个强连通分量可以与一个点等价,其权值为内部最小的权值)。
代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<stack>
#include<algorithm>
using namespace std;
const int maxn = 1005;
const int maxm = maxn*maxn;
const int inf =999999;
struct node{
int v,u,next;
}edge[ maxm ];
int head[ maxn ],cnt;
int vis[ maxn ],low[ maxn ],dfn[ maxn ],id;
int n,m,ans1;
int cost[ maxn ];
int belong[ maxn ],inde[ maxn ];//缩点,入度
int X[maxn],Y[maxn],R[maxn];
stack<int>q;
void init(){
cnt=0;
id=0;
ans1=0;
memset( vis,0,sizeof( vis ));
memset( dfn,-1,sizeof(dfn) );
memset( low,-1,sizeof( low ));
memset( head,-1,sizeof( head ));
}
void addedge( int a,int b ){
edge[ cnt ].v=a;
edge[ cnt ].u=b;
edge[ cnt ].next=head[ a ];
head[ a ]=cnt++;
}
void tarjan( int now ){
dfn[ now ]=low[ now ]=id++;
vis[ now ]=1;
q.push( now );
for( int i=head[ now ];i!=-1;i=edge[ i ].next ){
int next=edge[ i ].u;
if( dfn[ next ]==-1 ){
tarjan( next );
low[ now ]=min( low[ now ],low[ next ]);
}
else if( vis[ next ]==1 ){
low[ now ]=min( low[ now ],dfn[ next ] );
}
}
if( low[ now ]==dfn[ now ] ){
ans1++;
while( 1 ){
int tmp;
tmp=q.top(),q.pop();
vis[ tmp ]=0;
belong[ tmp ]=ans1;
if( tmp==now ) break;
}
}
}
int main(){
int t,T=0;
scanf("%d",&t);
while(t--)
{
init();
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d%d",&X[i],&Y[i],&R[i],&cost[i]);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j) continue;
long long now=1LL*(X[j]-X[i])*(X[j]-X[i])+1LL*(Y[j]-Y[i])*(Y[j]-Y[i]);
if(now<=1LL*R[i]*R[i])
addedge(i,j);
}
}
while( !q.empty() ) q.pop();
for( int i=1;i<=n;i++ ){
if( dfn[ i ]==-1 ){
tarjan( i );
}
}
int a,b;
memset( inde,0,sizeof( inde ));
for( int i=0;i<cnt;i++ ){
a=edge[ i ].v,b=edge[ i ].u;
if( belong[ a ]!=belong[ b ] ){
inde[ belong[ b ] ]++;
}
}
int ANS1,ANS2;
ANS1=ANS2=0;
int tmp_cnt[ maxn ];
for( int i=1;i<=ans1;i++ ){
if( inde[ i ]==0 )
ANS1++;//统计缩点之后,入度为0的点
tmp_cnt[ i ]=inf;
}
for( int i=1;i<=n;i++ ){
int tmp=belong[ i ];
if( inde[ tmp ]==0 ){
tmp_cnt[ tmp ]=min( tmp_cnt[ tmp ],cost[ i ] );
}
}
for( int i=1;i<=ans1;i++ ){
if( tmp_cnt[ i ]!=inf )
ANS2+=tmp_cnt[ i ];
}
printf("Case #%d: %d\n",++T,ANS2);
}
return 0;
}