题目大意

二维平面上有 n 个爆炸桶,i−thi-thi−th爆炸桶位置为 (xi,yi)(x_i, y_i)(xi​,yi​) 爆炸范围为 rir_iri​ ,且需要 cic_ici​ 的价格引爆,求把所有桶引爆所需的钱。

分析

通过求有向图的强连通分量,求出所有爆炸块(满足引爆一个块内的任意一个爆炸桶就可以摧毁这个块内的爆炸桶),然后把所有爆炸块视为一个爆炸桶,价值为爆炸块内的价值最小值,然后重建有向图,将新建的有向图所有入度为 0 的点的价值相加,就是答案。

AC-Code

#include <bits/stdc++.h>

using namespace std;

const int MAXN = 1100;  // 点数
const int MAXM = 1000100; // 边数
struct Edge {
int to, next;
} edge[MAXM]; // 只有这里写的是 MAXM int head[MAXN], tot;
int Low[MAXN], DFN[MAXN], Stack[MAXN], Belong[MAXN]; //Belong 数组的值是 1 ~ scc
int Index, top;
int scc; // 强连通分量的个数
bool Instack[MAXN];
int num[MAXN]; // 各个强连通分量包含点的个数,数组编号 1 ~ scc
// num 数组不一定需要,结合实际情况 void addedge(int u, int v) {
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
} void Tarjan(int u) {
int v;
Low[u] = DFN[u] = ++Index;
Stack[top++] = u;
Instack[u] = true;
for (int i = head[u]; i != -1; i = edge[i].next) {
v = edge[i].to;
if (!DFN[v]) {
Tarjan(v);
if (Low[u] > Low[v])
Low[u] = Low[v];
} else if (Instack[v] && Low[u] > DFN[v])
Low[u] = DFN[v];
}
if (Low[u] == DFN[u]) {
scc++;
do {
v = Stack[--top];
Instack[v] = false;
Belong[v] = scc;
num[scc]++;
} while (v != u);
}
} void solve(int N) {
memset(DFN, 0, sizeof(DFN));
memset(Instack, false, sizeof(Instack));
memset(num, 0, sizeof(num));
Index = scc = top = 0;
for (int i = 1; i <= N; i++)
if (!DFN[i])
Tarjan(i);
} void init() {
tot = 0;
memset(head, -1, sizeof(head));
} struct node {
int x, y, r, c; bool in_boom(const node &other) const {
return hypot(abs(x - other.x), abs(y - other.y)) <= r;
}
}; node nodeList[1100];
int n; void init_graph1() {
init();
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
if (i == j) continue;
if (nodeList[i].in_boom(nodeList[j]))
addedge(i, j);
}
}
} struct Graph {
struct Node {
int deg;
int value;
};
Node node[MAXN]; void init() {
for (int i = 0; i < n + 5; ++i) {
node[i].deg = 0;
node[i].value = INT_MAX;
}
} void add_edge(int from, int to) {
if (from != to)
node[to].deg++;
}
}; Graph graph;
int ans; void tp_init() {
graph.init();
for (int i = 1; i <= n; ++i) {
graph.node[Belong[i]].value = min(graph.node[Belong[i]].value, nodeList[i].c);
for (int j = 1; j <= n; ++j) {
if (i == j) continue;
if (nodeList[i].in_boom(nodeList[j]))
graph.add_edge(Belong[i], Belong[j]);
}
}
} void tp() {
ans = 0;
tp_init(); for (int i = 1; i <= scc; ++i) {
if (graph.node[i].deg == 0) {
ans += graph.node[i].value;
}
}
} void solve() {
int t;
cin >> t;
for (int ts = 0; ts < t; ++ts) {
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> nodeList[i].x >> nodeList[i].y >> nodeList[i].r >> nodeList[i].c;
}
init_graph1();
solve(n);
tp();
cout << "Case #" << ts + 1 << ": " << ans << endl;
}
} int main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
long long test_index_for_debug = 1;
char acm_local_for_debug;
while (cin >> acm_local_for_debug) {
cin.putback(acm_local_for_debug);
if (test_index_for_debug > 20) {
throw runtime_error("Check the stdin!!!");
}
auto start_clock_for_debug = clock();
solve();
auto end_clock_for_debug = clock();
cout << "Test " << test_index_for_debug << " successful" << endl;
cerr << "Test " << test_index_for_debug++ << " Run Time: "
<< double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
cout << "--------------------------------------------------" << endl;
}
#else
solve();
#endif
return 0;
}

【HDU5934】Bomb——有向图强连通分量+重建图的更多相关文章

  1. 图的连通性:有向图强连通分量-Tarjan算法

    参考资料:http://blog.csdn.net/lezg_bkbj/article/details/11538359 上面的资料,把强连通讲的很好很清楚,值得学习. 在一个有向图G中,若两顶点间至 ...

  2. 有向图强连通分量的Tarjan算法

    有向图强连通分量的Tarjan算法 [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G ...

  3. 有向图强连通分量 Tarjan算法

    [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极 ...

  4. 【转】有向图强连通分量的Tarjan算法

    原文地址:https://www.byvoid.com/blog/scc-tarjan/ [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly con ...

  5. 有向图强连通分量的Tarjan算法和Kosaraju算法

    [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极 ...

  6. 算法笔记_144:有向图强连通分量的Tarjan算法(Java)

    目录 1 问题描述 2 解决方案 1 问题描述 引用自百度百科: 如果两个顶点可以相互通达,则称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连 ...

  7. 有向图强连通分量的Tarjan算法及模板

    [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强联通(strongly connected),如果有向图G的每两个顶点都强联通,称有向图G是一个强联通图.非强联通图有向 ...

  8. 【转载】有向图强连通分量的Tarjan算法

    转载地址:https://www.byvoid.com/blog/scc-tarjan [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly conn ...

  9. 有向图强连通分量Tarjan算法

    在https://www.byvoid.com/zhs/blog/scc-tarjan中关于Tarjan算法的描述非常好,转述如下: 首先解释几个概念: 有向图强连通分量:在有向图G中,如果两个顶点间 ...

随机推荐

  1. python 初学者

    明确学习目标,不急于求成 当下是一个喧嚣.浮躁的时代.我们总是被生活中大量涌现的热点所吸引,几乎没有深度阅读和思考的时间和机会.我始终认为,学习是需要沉下心来慢慢钻研的,是长 期的:同时,学习不应该被 ...

  2. 聊聊RabbitMQ那一些事儿之一基础应用

    聊聊RabbitMQ那一些事儿之一基础应用 Hi,各位热爱技术的小伙伴您们好,今年的疫情害人啊,真心祝愿您和您的家人大家都平平安安,健健康康.年前到现在一直没有总结点东西,写点东西,不然久了自己感觉自 ...

  3. PHP算法练习2:(175. 组合两个表)

    练习地址:https://leetcode-cn.com/problems/combine-two-tables/ 表1: Person +-------------+---------+ | 列名 ...

  4. mac 使用命令行向 github 提交代码

    让 mac 本地和自己的 github 网站建立连接(ssh) 下载安装 git 网址: https://git-scm.com/downloads 查看安装是否成功: git -version $ ...

  5. AE脚本:把SubRip/SRT/TXT/VTT字幕导入到AE

    脚本介绍 如果您需要在视频中嵌入字幕以进行网络或磁带传送,那么这个脚本则非常有用.可以将SubRip/SRT/TXT/VTT字幕格式文件通过 pt_ImportSubtitles脚本直接加载到AE软件 ...

  6. beego的安装以及bee的安装和使用

    beego的安装以及bee的安装和使用 一.beego的安装 1.beego是什么 beego 是一个快速开发 Go 应用的 HTTP 框架,他可以用来快速开发 API.Web 及后端服务等各种应用, ...

  7. 我折腾的shell笔记

    目录 Mac一些常用的快捷键记录 iTerm2或者命令行相关 Mac桌面上或者某目录下操作 一些实用脚本示例 代码无提示或者其他抽风症状,清除Xcode缓存 查看当前网络ip地址 日常提交推送git代 ...

  8. JAVA有关位运算的全套梳理

    一.在计算机中数据是如何进行计算的? 1.1:java中的byte型数据取值范围 我们最开始学习java的时候知道,byte类型的数据占了8个bit位,每个位上或0或1,左边第一位表示符号位,符号位如 ...

  9. Anroid关于fragment控件设置长按事件无法弹出Popupwindows控件问题解决记录

    一.问题描述     记录一下最近在安卓的gragment控件中设置长按事件遇见的一个坑!!!     在正常的activity中整个活动中设置长按事件我通常实例化根部局,例如LinearLayout ...

  10. python学习的新篇章--面向对象

    面向对象的学习笔记   关键要素: 类:class 用来描述具有相同的属性和方法的对象的集合,它定义了该集合中每个对象所共有的属性和方法.   数据成员: 类的不同属性数据   对象: 类的一个实例 ...