牛客 - Strange Bulbs(bitset优化拓扑)

Posted Frozen_Guardian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛客 - Strange Bulbs(bitset优化拓扑)相关的知识,希望对你有一定的参考价值。

题目链接:点击查看

题目大意:给出一张 n 个点和 m 条边组成的有向无环图,每个节点都有一个开关和一个灯泡,初始时节点 1 的灯泡是亮的,每次操作开关可以将当前灯泡的状态置反,且会对子节点的开关产生连锁反应,问至少需要操作多少次才能将所有的灯泡关上

题目分析:看到有向无环图首先想到拓扑,但是如果暴力拓扑转移每个点的状态的话,时间复杂度是 n * n 级别的,必定会超时,但是看到数据范围其实有经验的同学就会想到利用 bitset 优化了,可以优化掉 64 层的时空复杂度,经过优化后的时空复杂度就可以暴力转移了,令每个节点都维护一个 bitset 变量,记录一下前面有哪些节点会影响到该节点,如果有奇数个节点影响到了该节点的话,因为每个灯泡初始时都是灭着的,所以需要利用一次操作将其关闭,如果是偶数个则直接跳过即可,每次利用位运算向下传递状态就好了

代码:
 

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;
   
typedef long long LL;
   
typedef unsigned long long ull;
   
const int inf=0x3f3f3f3f;
   
const int N=4e4+100;

bitset<N>b[N];

vector<int>node[N];

int du[N],n,m;

int topo()

	int ans=0;
	queue<int>q;
	q.push(1);
	b[1][1]=1;
	while(q.size())
	
		int u=q.front();
		q.pop();
		if(b[u].count()&1)
		
			b[u][u]=1;
			ans++;
		
		for(auto v:node[u])
		
			b[v]|=b[u];
			if(--du[v]==0)
				q.push(v);
		
	
	return ans;


int main()

#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//  freopen("output.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);
	scanf("%d%d",&n,&m);
	while(m--)
	
		int u,v;
		scanf("%d%d",&u,&v);
		node[u].push_back(v);
		du[v]++;
	
	printf("%d\\n",topo());
















    return 0;

 

以上是关于牛客 - Strange Bulbs(bitset优化拓扑)的主要内容,如果未能解决你的问题,请参考以下文章

牛客练习赛85 D.数学家的迷题(bitset暴力)

牛客挑战赛 47C条件(floyd求闭包bitset优化)

2021牛客暑期多校训练营8 F.Robots 离线分治+bitset

2021牛客暑期多校训练营7 J. xay loves Floyd 预处理最短路+bitset

zoj 2976 Light Bulbs(暴力枚举)

Light bulbs (树状数组模板题)