HDU6072(Kosaraju求强联通分量+位运算)
来源:互联网 发布:java八种基本类型 编辑:程序博客网 时间:2024/06/06 00:25
题意:给你n个点,和一个n*n的01矩阵表示边,有m次询问,问更改k条边后的强连通分量。
题解:对于每个询问,求出强连通分量,那么一个点数为t的强连通分量对答案的贡献为
利用Kosaraju算法,只需要在正反图各做一次DFS即可求出强连通分量。面对稠密图,Kosaraju算法的瓶颈在于寻找与点x相连且未访问过的点。可以用二进制数来表示边表
/*利用Kosaraju算法,只需要在正反图各做一次DFS即可求出强连通分量。面对稠密图,Kosaraju算法的瓶颈在于寻找与点x相连且未访问过的点。可以用二进制数来表示边表$g_x$,以及未访问过的点集S。*/#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define N 260struct BIT{ unsigned int b[8]; /* 如果x==0,则b数组全置为0 如果x==0xff,则b数组全置为1 */ void reset(int x){memset(b,x,sizeof(b));} void flip(int x){b[x>>5]^=1U<<(x&31);} //得到BIT的x位是0还是1 int get(int x){return (b[x>>5]>>(x&31))&1;}}g1[N],g2[N],vis;//g1表示正图,g2表示反图,vis表示未访问过的点集int sta[N];int n,top,cnt;//得到s中最右边的1之前0的个数inline int get_x(unsigned int s){ int x=0; while(!(s&1)) { ++x;s>>=1; } return x;}void dfs1(int x){ vis.flip(x); unsigned int s; for(int i=0;i<8;++i) { while(1) { //s位可以还未访问的点集 s=vis.b[i]&g1[x].b[i]; if(s==0) break; dfs1((i<<5)|get_x(s)); } } sta[++top]=x;}void dfs2(int x){ vis.flip(x);++cnt; unsigned s; int y; for(int i=0;i<8;++i) { while(true) { s=vis.b[i]&g2[x].b[i]; if(s==0) break; dfs2((i<<5)|get_x(s)); } }}int main(){ int ca,m; scanf("%d",&ca); char st[N]; while(ca--) { scanf("%d%d",&n,&m); for(int i=0;i<n;++i) g1[i].reset(0),g2[i].reset(0); for(int i=0;i<n;++i) { scanf("%s",st); for(int j=0;j<n;++j) if(st[j]=='1') g1[i].flip(j),g2[j].flip(i); } int k,u,v; while(m--) { scanf("%d",&k); for(int i=1;i<=k;++i) { scanf("%d%d",&u,&v); --u;--v; g1[u].flip(v);g2[v].flip(u); } vis.reset(0xff);top=0; for(int i=0;i<n;++i) if(vis.get(i)) dfs1(i); vis.reset(0xff); int ans=0; for(int i=top;i>0;--i) if(vis.get(sta[i])) { //cnt表示一个强联通分量中点的数量 cnt=0; dfs2(sta[i]); ans+=cnt*(cnt-1)/2; } printf("%d\n",ans); } } return 0;}
阅读全文
0 0
- HDU6072(Kosaraju求强联通分量+位运算)
- 强联通分量-kosaraju
- Kosaraju算法---强联通分量
- POJ 2186 Popular Cows Kosaraju求强联通分量
- 强联通分量的KOSARAJU算法
- poj 2186 Popular Cows(kosaraju求联通分量)
- hdu 4635 Strongly connected Kosaraju/Tarjan求强联通分量大小
- 强连通分量(kosaraju)
- tarjan求强联通分量
- tarjan求强联通分量
- 关于求强连通分量的Kosaraju
- 【POJ1236】Network of Schools 强联通分量缩点(本文kosaraju)
- poj 2186 Popular Cows 强联通分量tarjan/Kosaraju
- poj 1236 Network of Schools 强联通分量Kosaraju
- 算法笔记(二):tarjan 算法求强联通分量
- 强连通分量(Tarjan、Kosaraju)
- tanjan算法求强联通分量
- 图论--Tarjan求强联通分量
- JavaScript运算符(操作符)详解(1)----复杂运算符
- exclipse报错问题
- 【PAT】【Advanced Level】1047. Student List for Course (25)
- cmd 运行php 文件
- Connect them ZOJ
- HDU6072(Kosaraju求强联通分量+位运算)
- ZigZag Conversion
- 邻接表 有向图 是否有环 C实现 (dfs
- 【PAT】【Advanced Level】1048. Find Coins (25)
- Android ContentProvider之ContentObserver内容观察者
- Linux基础
- 堆栈的简单介绍
- Linux ping命令 【转】
- Java中文件的压缩处理