zoukankan      html  css  js  c++  java
  • HDU

    题意:给出你N个炸弹坐标,以及每个的爆炸范围,引爆炸弹所需的花费。如果某个炸弹在另一个的爆炸范围以内,则可以被另一个炸弹引爆(间接引爆)。问引爆所有炸弹所需的最小花费

    思路:把炸弹看作一个点,间接引爆就相当于一条有向边。最终所形成的图中,我们去找强连通分量。每个分量中花费最小的cost 以及 入度为0的 炸弹cost之和 即为所求。

    这里我们使用tarjan来缩点求强连通分量。

    完整代码:(注意 要开long long)

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <stack> 
    #include <cmath>
    #define ll long long 
    #define IOS ios::sync_with_stdio(0); cin.tie(0);
    using namespace std;
    const int maxn = 1e3+3;
    const int maxe = 1e6+1;
    struct Edge{
        int v,next;
    }edge[maxe];
    struct Bomb{
        ll x,y;
        ll c;
        double r;
    }bomb[maxn];
    int head[maxn];
    int indeg[maxn],outdeg[maxn];
    int dfn[maxn],low[maxn];
    int belong[maxn],instack[maxn];
    int top,idex,num,n;
    stack<int>S;
    void init(){
        top = idex = num = 0;
        memset(head,-1,sizeof(head));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(indeg,0,sizeof(indeg));
        memset(instack,0,sizeof(instack));
        memset(belong,0,sizeof(belong));
    }
    void add(int u,int v){
        edge[top].v = v;
        edge[top].next = head[u];
        head[u] = top++;
    }
    void tarjan(int x){
        dfn[x] = low[x] = ++idex;
        instack[x] = 1;
        S.push(x);
        for(int i = head[x]; ~i ;i =edge[i].next){
            int v = edge[i].v;
            if(!dfn[v]){
                tarjan(v);
                low[x] = min(low[x],low[v]);
            }else if(instack[v]){
                low[x] = min(low[x],dfn[v]);
            }
        }
        if(low[x] == dfn[x]){
            int t;
            ++num;
            do{
                t = S.top();
                belong[t] = num;
                instack[t] = 0;
                S.pop();
            }while(t != x);
        }
        
    }
    bool check(int i, int j) {
        return 1LL * sqrt(1LL * (bomb[i].x - bomb[j].x) * (bomb[i].x - bomb[j].x) + 1LL *
         (bomb[i].y - bomb[j].y) * (bomb[i].y -bomb[j].y)) <= bomb[i].r;
    }
    int main(){
        IOS;
        int T,Case;
        cin>>T;
        Case = 0;
        while(T--){
            init();
            cin>>n;
            for(int i =1;i <= n ;i++){
                cin>>bomb[i].x>>bomb[i].y>>bomb[i].r>>bomb[i].c;
            }
            for (int i = 1; i <= n; i++)
                for (int j = 1; j <= n; j++) if (i != j && check(i, j))
                    add(i, j);
            for(int i =1;i <= n;i++){
                if(!dfn[i]) tarjan(i);
            }
            //遍历边判断两点是否在同一个连通分量中,如果在则入度加1
            for(int i =1;i <= n;i++){
                for(int j = head[i]; ~j ;j = edge[j].next){
                    if(belong[i] == belong[edge[j].v]) continue;
                    indeg[belong[edge[j].v]]++;//记录入度
                }
            }
            ll ans;
            ll res;
            ans = 0;
            for(int i = 1; i<= num; i++){
                if(!indeg[i]){
                    res = 1e18;
                    //找到该分量中最小的cost
                    for(int j = 1;j<=n;j++){
                        if(belong[j] == i) res = min(res,bomb[j].c);            
                    }
                    ans += res;
                }
            }
            cout<<"Case #"<<++Case<<": "<<ans<<endl;
        }
        return 0;
    }
  • 相关阅读:
    leetcode之String to Integer (atoi)
    初次思考
    leetcode之Reverse Words in a String
    Leetcode之Database篇
    在项目中添加类
    创建项目
    配置Eclipse

    递归
    多态
  • 原文地址:https://www.cnblogs.com/Tianwell/p/11317226.html
Copyright © 2011-2022 走看看