非常有灵性的一道强连通分量。乍一看是道模板题,然而需要用bitset优化时间复杂度至1/64;bitset什么鬼啊喂,很佩服赛场上唯一做出来的大佬orz;
常规部分,学习了scc模板求强连通分量;
第一遍dfs给图上的倒序编号(最后访问到的标最小号);
第二遍在所有边反向后的图上dfs,从一个强连通分图上的点不可能访问到其他强分图上的点(为什么还没有理解)
cmp[I] = k 表示编号为i的点属于编号为k的强分图;
scc结束;
本题中节点数为t的强分图,对答案贡献t*(t-1)/2;
难点就是bitset 的理解和使用了(紧张);
首先试了下头文件#include
然而长度为8的bitset<8> b; 只能放8个0/1;
并不是很神奇;遂放弃,看大神的手写版;
这就非常有灵性了。
reset(int x) 好理解,初始化。x=0 b为0,x = 0xff,无限大;
flip(int x) 不好理解。8位,256个数,把x这个数0变1,1变0;
b[x>>5] 每一位表示32个数,x>>5确定x属于哪一位管;
将这一位加上2的x%32次方,表示这个数的存在
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<stack>
#include<queue>
#include<bitset>
using namespace std;
using std::bitset;
typedef long long ll;
const int maxv = 255;
struct BIT{
unsigned int b[8];
void reset(int x){ memset(b, x, sizeof(b)); }
void flip(int x){ b[x >> 5] ^= 1U << (x & 31); }
int get(int x){ return (b[x >> 5] >> (x & 31)) & 1; }
}G[maxv], rG[maxv], vis;
int V;
vector<int> vs;
int cmp[maxv];
int cnt = 0;
inline int ctz(unsigned int s)
{
int x = 0;
while (!(s & 1))
{
++x; s >>= 1;
}
return x;
}
void dfs(int v){
vis.flip(v);
unsigned int s;
for (int i = 0; i < 8; ++i){
while (1){
s = vis.b[i] & G[v].b[i];
if (!s) break;
//这里是什么原理依然没有搞清楚orz;
dfs((i << 5)| ctz(s));
}
}
vs.push_back(v);
}
void rdfs(int v){
++cnt;
vis.flip(v);
unsigned int s;
for (int i = 0; i < 8; i++){
while (1){
s = vis.b[i] & rG[v].b[i];
if (!s) break;
rdfs((i << 5 )| ctz(s));
}
}
}
void scc(){
vis.reset(0xff);vs.clear();
for (int i = 0; i < V; i++){
if (vis.get(i)) dfs(i);
}
vis.reset(0xff);
ll ans = 0;
for (int i = vs.size() - 1; i >= 0; i--){
if (vis.get(vs[i])) {
cnt = 0;
rdfs(vs[i]);
ans += cnt*(cnt - 1) / 2;
}
}
printf("%lld\n", ans);
}
char c;
int t, m;
int main(){
scanf("%d", &t);
while (t--){
scanf("%d%d", &V, &m);
for (int i = 0; i <= V; i++){
G[i].reset(0);
rG[i].reset(0);
}
for (int i = 0; i < V; i++){
char g[maxv];
scanf("%s", g);
for (int j = 0; j < V; j++){
if (g[j] == '1') {
G[i].flip(j);
rG[j].flip(i);
}
}
}
while (m--){
int k; scanf("%d", &k);
for (int i = 1; i <= k; ++i){
int u, v;
scanf("%d%d", &u, &v);
G[u - 1].flip(v - 1);
rG[v - 1].flip(u - 1);
}
scc();
}
}
}