消消乐
消消乐
题意
在一个网格图中,有两种功能方块,一种可以引爆同一行的功能方块,一种可以引爆同一列的。
求最少引爆多少个功能方块能消除所有功能方块。
思路
先想到建图,每个横向的功能方块向同一行的功能方块连有向边,每个竖向的功能方块向同一列的功能方块脸有向边,最后缩点求出入度为
但这样连边变得数量最多是
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 5;
int n, m, r, ans;
int t[N], x[N], y[N], sc, scc[N], in[N];
int low[N], dfn[N], cnt, stk[N], top;
bool instk[N], u[N];
vector <int> E[N];
void tarjan(int x) {
low[x] = dfn[x] = ++ cnt;
stk[++ top] = x; instk[x] = 1;
for (auto y : E[x]) {
if (!dfn[y]) {
tarjan(y);
low[x] = min(low[x], low[y]);
} else if (instk[y])
low[x] = min(low[x], dfn[y]);
}
if (low[x] == dfn[x]) {
sc ++;
while (top && stk[top] != x) {
scc[stk[top]] = sc;
instk[stk[top]] = 0;
if (stk[top] <= r) u[sc] = 1;
top --;
}
scc[stk[top]] = sc;
if (stk[top] <= r) u[sc] = 1;
instk[stk[top]] = 0;
top --;
}
}
int main() {
freopen("lele.in", "r", stdin);
freopen("lele.out", "w", stdout);
cin >> n >> m >> r;
for (int i = 1; i <= r; i ++) {
cin >> t[i] >> x[i] >> y[i];
E[r + x[i]].push_back(i);
E[r + n + y[i]].push_back(i);
if (t[i] == 1) E[i].push_back(r + x[i]);
else E[i].push_back(r + n + y[i]);
}
for (int i = 1; i <= r + n + m; i ++)
if (!dfn[i]) tarjan(i);
for (int i = 1; i <= r + n + m; i ++) {
for (auto y : E[i]) {
if (scc[y] != scc[i] && u[scc[i]] && u[scc[y]]) {
in[scc[y]] ++;
}
}
}
for (int i = 1; i <= sc; i ++)
if (in[i] == 0 && u[i]) ans ++;
cout << ans << "\n";
return 0;
}
本文来自博客园,作者:maniubi,转载请注明原文链接:https://www.cnblogs.com/maniubi/p/18471009,orz
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】