hdoj 5934 Bomb

来源:互联网 发布:淘宝500字差评范文 编辑:程序博客网 时间:2024/06/05 10:53

题目链接:Bomb

题目大意:现在有一些炸弹,有他的坐标,爆炸半径范围以及爆炸缩需要的价值,问要引爆所有的炸弹最少需要多少花费

题目思路:因为A能引爆B导致B引爆C,所以A能引爆C,但是A引爆B不代表B能引爆A,因为爆炸半径不一样嘛,所以建有向边,强连通分量缩点,然后找入度为零的联通快,必须引爆,不然没办法全部炸掉,引爆的花费是这个联通块的里面所有点的最小价值,然后加起来就好了

#include <map>#include <set>#include <cmath>#include <stack>#include <queue>#include <vector>#include <cstdio>#include <string>#include <utility>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;typedef long long ll;const int maxn = 20010;const int maxm = 1e5+10;vector<int>Edge[maxm];stack<int>S;int T,n;ll x[maxn],y[maxn],r[maxn],c[maxn];int Dfn[maxn],Low[maxn],sccno[maxn],tclock,sccnt;int InDeg[maxn],mincostscc[maxn];void tarjan(int u){    Dfn[u] = Low[u] = ++tclock;    S.push(u);    for(int i = 0;i < Edge[u].size();i++){        int v = Edge[u][i];        if(!Dfn[v]){            tarjan(v);            Low[u] = min(Low[u],Low[v]);        }        else if(!sccno[v]){            Low[u] = min(Low[u],Dfn[v]);        }    }    if(Low[u] == Dfn[u]){        sccnt ++;        int v = -1;        while(v != u){            v = S.top();            S.pop();            sccno[v] = sccnt;            mincostscc[sccnt] = min(mincostscc[sccnt],(int)c[v]);        }    }}void findscc(int n){    tclock = sccnt = 0;    memset(Dfn,0,sizeof(Dfn));    memset(Low,0,sizeof(Low));    memset(sccno,0,sizeof(sccno));    memset(mincostscc,0x3f3f3f3f,sizeof(mincostscc));    for(int i = 1;i <= n;i++)        if(!Dfn[i]) tarjan(i);}bool judge(ll x1,ll y1,ll x2,ll y2,ll r){    if((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2) <= r*r) return true;    return false;}int solve(int n){    memset(InDeg,0,sizeof(InDeg));    for(int u = 1;u <= n;u++){        for(int i = 0;i < Edge[u].size();i++){            int v = Edge[u][i];            if(sccno[u] != sccno[v]){                InDeg[sccno[v]]++;            }        }    }    int minn = 0;    for(int i = 1;i <= sccnt;i++){        if(InDeg[i] == 0) minn += mincostscc[i];    }    return minn;}int main(){    scanf("%d",&T);    for(int Case = 1;Case <= T;Case++){        scanf("%d",&n);        for(int i = 1;i <= n;i++) scanf("%lld%lld%lld%lld",&x[i],&y[i],&r[i],&c[i]);        for(int i = 1;i <= n;i++) Edge[i].clear();        for(int i = 1;i <= n;i++){            for(int j = i+1;j <= n;j++){                if(judge(x[i],y[i],x[j],y[j],r[i])) Edge[i].push_back(j);                if(judge(x[i],y[i],x[j],y[j],r[j])) Edge[j].push_back(i);            }        }        findscc(n);        printf("Case #%d: %d\n",Case,solve(n));    }    return 0;}
原创粉丝点击