Bomb HDU - 5934 (Tarjan)

#include<map>
#include<set>
#include<ctime>
#include<cmath>
#include<stack>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lowbit(x) (x & (-x))

typedef unsigned long long int ull;
typedef long long int ll;
const double pi = 4.0*atan(1.0);
const int inf = 0x3f3f3f3f;
const int maxn = 1005;
const int maxm = 1000005;
const int mod = 10007;
using namespace std;

int n, m, tol, T;
int cnt, top, sz;
struct Edge {
    ll x;
    ll y;
    ll r;
    ll w;
};
struct Node {
    int u;
    int v;
    int next;
};
Node node[maxm];
Edge edge[maxn];
int head[maxn];
int dfn[maxn];
int low[maxn];
int fath[maxn];
int sta[maxn];
bool vis[maxn];
int point[maxn];
int ind[maxn];
ll cost[maxn];

void init() {
    cnt = tol= top = sz = 0;
    memset(ind, 0, sizeof ind);    
    memset(sta, 0, sizeof sta);
    memset(dfn, 0, sizeof(dfn));
    memset(low, 0, sizeof(low));
    memset(fath, 0, sizeof(fath));
    memset(head, -1, sizeof(head));
    memset(cost, inf, sizeof cost);
    memset(point, 0, sizeof point);
    memset(vis, false, sizeof(vis));
}

ll calc(int i, int j) {
    ll x1 = edge[i].x;
    ll x2 = edge[j].x;
    ll y1 = edge[i].y;
    ll y2 = edge[j].y;
    ll ans = (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2);
    return ans;
}

void addnode(int u, int v) {
    node[tol].u = u;
    node[tol].v = v;
    node[tol].next = head[u];
    head[u] = tol++;
}

void dfs(int u) {
    int v;
    dfn[u] = low[u] = ++cnt;
    sta[sz++] = u;
    vis[u] = true;
    for(int i=head[u]; ~i; i=node[i].next) {
        v = node[i].v;
        if(!dfn[v]) {
            dfs(v);
            low[u] = min(low[u], low[v]);
        } else if(vis[v]) {
            low[u] = min(low[u], dfn[v]);
        }
    }
    if(low[u] == dfn[u]) {
        ++top;
        do{
            v = sta[--sz];
            vis[v] = false;
            point[v] = top;
        } while(v != u);
    }
}

void tarjan() {
    for(int u=1; u<=n; u++) {
        if(!dfn[u])    dfs(u);
    }
}

void solve() {
    for(int u=1; u<=n; u++) {
        for(int i=head[u]; ~i; i=node[i].next) {
            int v = node[i].v;
            if(point[u] != point[v])    ind[point[v]]++;
        }
    }
}

int main() {
    scanf("%d", &T);
    int cas = 1;
    while(T--) {
        init();
        scanf("%d", &n);
        for(int i=1; i<=n; i++)    scanf("%lld%lld%lld%lld", &edge[i].x, &edge[i].y, &edge[i].r, &edge[i].w);
        for(int i=1; i<=n; i++) {
            for(int j=1; j<=n; j++) {
                if(i == j)    continue;
                ll a = edge[i].r * edge[i].r;
                ll b = calc(i, j);
                if(a >= b)    addnode(i, j);
            }
        }
        tarjan();
//        for(int i=1; i<=n; i++)    printf("%d %d\n", i, point[i]);
        solve();
//        for(int i=1; i<=n; i++)    printf("%d %d\n", i, ind[point[i]]);
        for(int i=1; i<=n; i++) {
            if(!ind[point[i]]) {
                cost[point[i]] = min(cost[point[i]], edge[i].w);
            }
        }
        ll ans = 0;
        for(int i=1; i<=top; i++) {
            if(!ind[i])    ans += cost[i];
        }
        printf("Case #%d: %lld\n", cas++, ans);
    }
    return 0;
}
View Code

给出n个炸弹,然后炸弹有爆炸范围,当一个炸弹爆炸的时候,这个范围内的其他炸弹也会爆炸,所以我们可以把可以相互引爆的炸弹缩成一个点,然后对于缩完以后的点,如果我缩完点的点,判断他的入度,如果我的入度不为0,说明我这个点里面的小点可以通过别的炸弹引爆它,那就没必要去炸它了,如果我的入度是0的话,我就需要手动引爆,然后去找这个点里面的小的点的引爆的最小值,然后加起来就可以了

猜你喜欢

转载自www.cnblogs.com/H-Riven/p/9389733.html
今日推荐