hdu5934Bomb

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5934

题意:给定二维平面上n个炸弹,每个炸弹有引爆需要的费用,如果一个炸弹引爆那么在它的半径范围内的炸弹也会被引爆(不需要花费),求引爆所有炸弹的最小花费。

分析:每个炸弹向能炸到的炸弹连一条有向边,然后有向图缩点成一个DAG图,那么我们只需要花费引爆所有起点即可。

代码:

#include<map>
#include<set>
#include<stack>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<vector>
#include<string>
#include<stdio.h>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
const db eps=1e-5;
const int N=1e3+10;
const int M=1e6+10;
const ll MOD=1000000007;
const int mod=1000000007;
const int MAX=1000000010;
const double pi=acos(-1.0);
int tot,w[N],u[N],v[M],pre[M];
int x[N],y[N],r[N];
void add(int a,int b) {
    v[tot]=b;pre[tot]=u[a];u[a]=tot++;
}
int pd(int a,int b) {
    return 1ll*r[a]*r[a]>=1ll*(x[a]-x[b])*(x[a]-x[b])+1ll*(y[a]-y[b])*(y[a]-y[b]);
}
stack<int>S;
int scc_cnt,dfs_clock,head[N],sccno[N];
int dfs_scc(int a) {
    int i,x,lowa,lowv;
    S.push(a);
    head[a]=lowa=++dfs_clock;
    for (i=u[a];~i;i=pre[i])
    if (!head[v[i]]) {
        lowv=dfs_scc(v[i]);
        lowa=min(lowa,lowv);
    } else if (!sccno[v[i]]) lowa=min(lowa,head[v[i]]);
    if (head[a]==lowa) {
        scc_cnt++;
        while (1) {
            x=S.top();S.pop();
            sccno[x]=scc_cnt;
            if (x==a) break ;
        }
    }
    return lowa;
}
void find_scc(int n) {
    scc_cnt=dfs_clock=0;
    memset(head,0,sizeof(head));
    memset(sccno,0,sizeof(sccno));
    for (int i=1;i<=n;i++)
    if (!head[i]) dfs_scc(i);
}
int d[N],mi[N];
int main()
{
    int i,j,n,ca,T,ans;
    scanf("%d", &T);
    for (ca=1;ca<=T;ca++) {
        scanf("%d", &n);
        for (i=1;i<=n;i++) scanf("%d%d%d%d", &x[i], &y[i], &r[i], &w[i]);
        tot=0;memset(u,-1,sizeof(u));
        for (i=1;i<=n;i++)
            for (j=1;j<=n;j++)
            if (i!=j&&pd(i,j)) add(i,j);
        find_scc(n);
        for (i=1;i<=scc_cnt;i++) d[i]=0,mi[i]=100000;
        for (i=1;i<=n;i++) {
            mi[sccno[i]]=min(mi[sccno[i]],w[i]);
            for (j=u[i];~j;j=pre[j])
            if (sccno[i]!=sccno[v[j]]) d[sccno[v[j]]]++;
        }
        ans=0;
        for (i=1;i<=scc_cnt;i++)
        if (d[i]==0) ans+=mi[i];
        printf("Case #%d: %d\n", ca, ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值