HDU 6072 Logical Chain(Kosaraju+bitset)
2024-08-27 09:05:16
http://acm.hdu.edu.cn/showproblem.php?pid=6072
题意:
给你$n*n$的矩阵,每次修改k条边,让你计算其中能相互到达的点对有多少。
思路:
其实就是求强连通分量,如果一个强连通分量里有n个点,那么这里面的点对就有$n*(n-1)/2$。用Kosaraju计算即可,但是这样是会超时的,还需要用bitset来优化。
__builtin_函数中处理二进制位的函数:
int __builtin_ffs (unsigned x) 返回x中最后一个1是从右往左第几位
int __builtin_popcount (unsigned x) 返回x中1的个数
int __builtin_ctz (unsigned x) 返回x末尾0的个数(x等于0时未定义)
int __builtin_clz (unsigned x) 返回x中前导0的个数(x等于0时未定义)
int __builtin_parity (unsigned x) 返回x中1的奇偶性
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn=+; int n, m;
int num;
char s[maxn]; struct Bitset//用unsigned数组实现bitset,为了使用__builtin_ctz()
{
unsigned v[];//8个unsigned表示8*32=256位 void reset()//清零
{
for(int i=;i<;++i) v[i]=;
}
void set(int x)//把某一位设为1
{
v[x>>]|=1u<<(x&);
}
void flip(int x)//翻转某一位
{
v[x>>]^=1u<<(x&);
}
bool test(int x)//返回某一位是否为1
{
return v[x>>]>>(x&)&;
}
}vis, G[maxn], rG[maxn]; vector<int> S; void dfs1(int u)
{
vis.flip(u);
for(int i=;i<;i++)
{
while(true)
{
unsigned tmp=vis.v[i]&G[u].v[i]; //tmp就计算出了可以访问的点
if(!tmp) break;
dfs1(i<<|__builtin_ctz(tmp)); //计算出tmp末尾有多少0,有多少0就代表了它是第几位,这儿的话一个点一个点的来
}
}
S.push_back(u);
} void dfs2(int u)
{
vis.flip(u);
++num;
for(int i=;i<;i++)
{
while(true)
{
unsigned tmp=vis.v[i]&rG[u].v[i];
if(!tmp) break;
dfs2(i<<|__builtin_ctz(tmp));
}
}
} void Kosaraju()
{
S.clear();
int ans=;
for(int i=;i<n;i++) vis.set(i);
for(int i=;i<n;i++) if(vis.test(i)) dfs1(i);
for(int i=;i<n;i++) vis.set(i);
for(int i=n-;i>=;i--)
{
if(vis.test(S[i]))
{
num=;
dfs2(S[i]);
ans+=num*(num-)/;
}
}
printf("%d\n",ans);
} int main()
{
//freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=;i<n;i++) G[i].reset(),rG[i].reset();
for(int i=;i<n;i++)
{
scanf("%s",s);
for(int j=;j<n;j++) if(s[j]=='')
{
G[i].flip(j);
rG[j].flip(i);
}
}
while(m--)
{
int t; scanf("%d",&t);
while(t--)
{
int u,v;
scanf("%d%d",&u,&v);
G[u-].flip(v-);
rG[v-].flip(u-);
}
Kosaraju();
}
}
return ;
}
最新文章
- echarts中显示效果option中必有的属性
- Address localhost:1099 is already in use 的错误
- struts2异常记录--java.lang.IllegalStateException
- 利用SOLR搭建企业搜索平台 之——Solr索引基本操作
- HttpURLConnection访问url的工具类
- Asp.net MVC 如何对所有用户输入的字符串字段做Trim处理
- iOS: FFmpeg编译和使用 学习
- HDU1097-A hard puzzle-快速幂+取模
- 【TCP协议】(1)---TCP协议详解
- [Swift]LeetCode57. 插入区间 | Insert Interval
- JAVA IO流 InputStream流 Read方法
- 二进制安装 kubernetes 1.12(五) - 运行测试实例
- map映射巧用 A-B Problems
- CPP之内存分配
- 分享 : 警惕MySQL运维陷阱:基于MyCat的伪分布式架构
- Luogu P1120 小木棍 [数据加强版]
- B1015 德才论 (25 分)
- Entity Framework(EF) Code First将实体中的string属性映射成text类型的几种方式
- Java 过滤特殊字符的 正则表达式
- DevExpress v17.2新版亮点——CodeRush篇(三)