2016ccpc杭州赛 hdu 5934 B.Bomb


Bomb

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 58    Accepted Submission(s): 27


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.
 

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
1T20
1N1000
108xi,yi,ri108
1ci104
 

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
liuyiding   |   We have carefully selected several similar problems for you:   5947  5946  5945  5944  5943 
题意:给你n个炸弹,知道炸弹的坐标和爆炸半径,还有引爆它的费用,一个炸弹可以引爆另一个炸弹。问引爆所有炸弹的最小费用。

思路:n^2枚举一个炸弹是否可以引爆另一个炸弹,可以就建边,然后就是一个普通的强连通分量问题,跑一遍tarjan,找入度为0的强联通分量的最小费用加起来就好了。下面给代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<utility>
#include<map>
#define maxn 1005
#define inf 0x3f3f3f3f
typedef long long LL;
using namespace std;
const int mod = 1e9 + 7;
int x[maxn], y[maxn], r[maxn], c[maxn], head[maxn], len, n;
int indeg[maxn]; //点的入度和出度数
int belong[maxn], low[maxn], dfn[maxn], scc, cnt;//dfn[]:遍历到u点的时间; low[]:u点可到达的各点中最小的dfn[v],ssc强连通分量数,belong表示该点在哪个联通块
int S[maxn], top, w[maxn];
bool vis[maxn];//v是否在栈中
struct node{
	int to, next;
}Edge[maxn*maxn];
void tarjan(int u)
{
	int v;
	dfn[u] = low[u] = ++cnt;//开始时dfn[u] == low[u]
	S[top++] = u;//不管三七二十一进栈
	vis[u] = true;
	for (int i = head[u]; ~i; i = Edge[i].next)
	{
		v = Edge[i].to;
		if (dfn[v] == 0)//如果v点还未遍历
		{
			tarjan(v);//向下遍历
			low[u] = low[u] < low[v] ? low[u] : low[v];//确保low[u]最小
		}
		else if (vis[v] && low[u] > dfn[v])//v在栈中,修改low[u]
			low[u] = dfn[v];
	}
	if (dfn[u] == low[u])//u为该强连通分量中遍历所成树的根
	{
		++scc;
		do
		{
			v = S[--top];//栈中所有到u的点都属于该强连通分量,退栈
			vis[v] = false;
			belong[v] = scc;
		} while (u != v);
	}

}

void solve()
{
	scc = top = cnt = 0;
	memset(dfn, 0, sizeof(dfn));
	memset(vis, false, sizeof(vis));
	for (int u = 1; u <= n; ++u)
		if (dfn[u] == 0)
			tarjan(u);
	memset(indeg, 0, sizeof(indeg));
	memset(w, inf, sizeof(w));
	for (int u = 1; u <= n; ++u){
		int x = belong[u];
		w[x] = min(w[x], c[u]);
		for (int i = head[u]; ~i; i = Edge[i].next)
		{
			int v = Edge[i].to;
			if (x != belong[v])
			{
				indeg[belong[v]]++;
			}
		}
	}
}
int main(){
	int t;
	scanf("%d", &t);
	for (int tcase = 1; tcase <= t; tcase++){
		scanf("%d", &n);
		for (int i = 1; i <= n; i++){
			scanf("%d%d%d%d", &x[i], &y[i], &r[i], &c[i]);
		}
		len = 0;
		memset(head, -1, sizeof(head));
		for (int i = 1; i <= n; i++){
			for (int j = 1; j <= n; j++){
				if (i == j)
					continue;
				if (pow(x[i] - x[j], 2) + pow(y[i] - y[j], 2) <= pow(r[i], 2)){
					Edge[len].to = j;
					Edge[len].next = head[i];
					head[i] = len++;
				}
			}
		}
		solve();
		LL ans = 0;
		for (int i = 1; i <= scc; i++){
			if (!indeg[i]){
				ans += w[i];
			}
		}
		printf("Case #%d: %lld\n", tcase, ans);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值