HDU [5934] Bomb [Strong Connected Component + Contraction Point]

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
- 1≤T≤20
- 1≤N≤1000
- -10^8\leq x_i,y_i,c_i\leq 10^8
- 1 \ leq c_i \ leq 10 ^ 4

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 

The main idea:

Given N bombs, each bomb has a coordinate (x, y), an explosion radius r and an artificial detonation cost c, if there is another bomb within the explosion range of a bomb, then if the bomb explodes, it will detonate For all bombs within the explosion range (not artificially detonated), seek the minimum artificial detonation cost for all bombs to explode. 

analysis:

First, it is obvious that a directed graph can be built according to the title, that is, for each bomb, there is a directed edge between the bomb and all the bombs within its explosion range.

Then, we need to find all the strongly connected components. Because all points within the same strong connected component (later abstracted as a point) can reach each other, so just detonating any one of them can detonate the entire strong connected component. To find the strong connected components, Tarjan can be used, and the minimum cost of artificial detonation in each strong connected component can be found during the search process.

After that, by reducing each strongly connected component to a point, a directed acyclic graph can be obtained. It is conceivable that all points with zero degrees in the graph (corresponding to strong connected components) must be detonated manually. Therefore, the sum of the minimum costs of all points with a zero degree (strongly connected component) is the answer.

See the code for specific explanation.

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>

#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
#define INF 0x3f3f3f3f

using namespace std;

const int maxn=1005;

struct bomb{
	ll x,y,r;
	int c;
};

bomb b[maxn];
vector<int> gra[maxn];//邻接表 
int low[maxn],dfn[maxn],sta[maxn],insta[maxn],belong[maxn],mincost[maxn],din[maxn];
int index,num,tp;

bool check(bomb a,bomb b){
	if((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)<=a.r*a.r)  return true;
	else return false;
}

void tarjan(int x){//Tarjan算法 
	dfn[x]=low[x]=++num;
	sta[++tp]=x;
	insta[x]=1;
	int len=gra[x].size();
	rep(i,0,len-1){
		int y=gra[x][i];
		if(!dfn[y]){
			tarjan(y);
			low[x]=min(low[x],low[y]);
		}
		else if(insta[y]==1)  low[x]=min(low[x],dfn[y]);
	}
	if(low[x]==dfn[x]){
		++index;
		int cost=INF;
		while(1){
			int y=sta[tp--];
			insta[y]=0;
			belong[y]=index;//每个点所属于的强连通分量的序号 
			cost=min(cost,b[y].c);//在强连通分量内找最小花费 
			if(y==x)  break;
		} 
		mincost[index]=cost;//保存每个强连通分量的最小花费 
	}
}

int main(){
	int t;
	scanf("%d",&t);
	rep(cas,1,t){
		int n;
		scanf("%d",&n);
		rep(i,1,n){
			scanf("%lld%lld%lld%d",&b[i].x,&b[i].y,&b[i].r,&b[i].c);
		}
		rep(i,0,maxn-1){
			gra[i].clear();
		}
		//建有向图 
		rep(i,1,n){
			rep(j,1,n){
				if(i!=j){
					if(check(b[i],b[j])){
						gra[i].push_back(j);					}
				}
			}
		}
		//初始化 
		memset(low,0,sizeof(low));
		memset(dfn,0,sizeof(dfn));
		memset(sta,0,sizeof(sta));
		memset(insta,0,sizeof(insta));
		memset(belong,0,sizeof(belong));
		memset(mincost,0,sizeof(mincost));
		memset(din,0,sizeof(din));
		index=num=tp=0;
		rep(i,1,n){
			if(!dfn[i]){
				tarjan(i);
			}
		}
		int i, j, v;
		for (i = 1; i <= n; i++){
			for (j = 0; j < gra[i].size(); j++){
				v = gra[i][j];
				if (belong[i] != belong[v]){  // 两点之间有边,但不是属于一个强联通分量的边
					din[belong[v]]++;	// 缩点后的点入度+1
				}
			}
		} 
		ll sum=0;
		rep(i,1,index){
			if(din[i]==0){
				sum+=(ll)mincost[i];
			}
		}
		printf("Case #%d: %lld\n",cas,sum);
	}
	return 0;
} 

 

Published 30 original articles · won 5 · 900 views

Guess you like

Origin blog.csdn.net/qq_42840665/article/details/98592399