牛客 - 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;
}

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/106799115