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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章