这是我见过最水的蓝题
这不就是拓扑排序板子题吗
题目大意;松鼠砸烂摄像头不被抓住
摄像头一个可以监视到另一个可以看做有向边,用邻接链表储存就好了,我也不知道邻接矩阵到底能不能过保险起见还是用邻接链表。 可以想到,松鼠要想不被抓住必须砸没有被别的摄像头监视的摄像头,那么就是入度为0的点,很简单的可以想到拓扑排序,因为拓扑排序就是从一个没有入边的点开始一步步走,每一步都是走同样没有入边的点(和多米诺骨牌很像)。拓扑排序里的没有入边和这里的没有被监控的摄像头可以很好的联系起来,就可以知道是用拓扑排序的了。
先找到第一个入度为0的点,然后从这个点开始继续往下找,如果在某一个点找不到其他的入度为0的点,那就是jj了,松鼠很可怜,必定会被抓住了那就输出剩余的摄像头的数量。 (数量可以用一个计数器每一次可以安全摧毁一个摄像头那计数器就加一,到不能的时候就输出摄像头的总数减去计数器,如果计数器等于摄像头的总数那就输出“YES”然后结束)
AC代码
#include<cstdio> #include<stack> using namespace std; struct node { int u,v,ne; }a[100000]; int n,num,num1; int head[10000]; int into[10000]; int bian[1000]; bool use[100000]; void add(int u,int v) { a[++num].ne = head[u]; a[num].u = u; a[num].v = v; head[u] = num; } int main() { stack<int>s; scanf("%d",&n); for(int i = 1;i <= n;++ i) { int x,y; scanf("%d%d",&x,&y); if(use[x] == false) bian[++ num1] = x; while(y --) { int xx; scanf("%d",&xx); add(x,xx); into[xx] ++; if(use[xx] == false) bian[++ num1] = xx; } } int qwq = 0; for(int i = 1;i <= num1;++ i) { if(into[bian[i]] == 0) { s.push(i);qwq ++; } } while(!s.empty()) { int u = s.top(); s.pop(); for(int i = head[u];i != 0;i = a[i].ne) { into[a[i].v] --; if(into[a[i].v] == 0) { s.push(a[i].v); qwq ++; } } } if(qwq == n) printf("YES "); else printf("%d ",n - qwq); return 0; }