题目地址:
https://www.luogu.com.cn/problem/P2712
题目描述:
食品店里有
n
n
n 个摄像头,这种摄像头很笨拙,只能拍摄到固定位置。现有一群胆大妄为的松鼠想要抢劫食品店,为了不让摄像头拍下他们犯罪的证据,他们抢劫前的第一件事就是砸毁这些摄像头。
为了便于砸毁摄像头,松鼠歹徒们把所有摄像头和摄像头能监视到的地方统一编号,一个摄像头能被砸毁的条件是该摄像头所在位置不被其他摄像头监视。
现在你的任务是帮松鼠们计算是否可以砸掉所有摄像头,如不能则输出还没砸掉的摄像头的数量。
输入格式:
第
1
1
1 行,一个整数
n
n
n,表示摄像头的个数。
第
2
2
2 到
n
+
1
n+1
n+1 行是摄像头的信息,包括:摄像头的位置
x
x
x,以及这个摄像头可以监视到的位置数
m
m
m,之后
m
m
m 个数
y
y
y 是此摄像头可以监视到的位置。(砸了这些摄像头之后自然这些位置就监视不到了)
输出格式:
若可以砸掉所有摄像头则输出“
YES
\texttt{YES}
YES ”,否则输出还没砸掉的摄像头的数量。(不带引号)
数据范围:
1
≤
n
≤
100
1 \leq n \leq 100
1≤n≤100。
0
≤
m
≤
100
0 \leq m \leq 100
0≤m≤100。
0
≤
x
,
y
≤
500
0 \leq x,y \leq 500
0≤x,y≤500。
先建图,然后做拓扑排序,可以用BFS,注意到入队的时候要判断一下那个位置是否有摄像头,如果没有摄像头的话不需要入队。代码如下:
#include <iostream>
#include <unordered_map>
#include <vector>
using namespace std;
const int N = 110;
int n;
unordered_map<int, vector<int>> g;
unordered_map<int, int> ind;
int q[N];
int topsort() {
int res = 0;
int hh = 1, tt = 1;
for (auto &[k, v] : g)
if (!ind[k]) q[tt++] = k;
while (hh < tt) {
int t = q[hh++];
res++;
for (auto &ne : g[t])
if (g.count(ne) && !--ind[ne]) q[tt++] = ne;
}
return n - res;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int x, m;
scanf("%d%d", &x, &m);
// 这句话是必要的,g含有x这个key说明x是有摄像头的
g.insert({x, {}});
for (int j = 1; j <= m; j++) {
int y;
scanf("%d", &y);
g[x].push_back(y);
}
}
for (auto &[k, v] : g)
for (int x : v)
if (g.count(x)) ind[x]++;
int res = topsort();
if (!res)
puts("YES");
else
printf("%d\n", res);
}
时空复杂度 O ( n + m ) O(n+m) O(n+m)。