HDU6072 Logical Chain

9 篇文章 0 订阅
4 篇文章 0 订阅

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=6072

Logical Chain

Problem Description

Every time you come across a problem you’ve never seen before, haven’t you thought of something that is familiar to you? If so, you might think of something else, then more and more things will come to your mind. This is what is called ‘‘Logical Chain’’. Lu Xun’s work also described such interesting phenomenon.

Assume there are n things, labeled by 1,2,…,n. Little Q’s mind can be expressed by a n×n matrix g. If he can think of j when he comes across i, then gi,j is 1, otherwise it’s 0. For two different things u and v, if u can lead to v directly or indirectly and v can also lead to u directly or indirectly, then the pair (u,v) is called a ‘‘Looping Pair’’.

Little Q’s mind changes all the time. On i-th day, there are ki positions (u,v) in matrix g flipped(0 to 1 and 1 to 0). Please write a program to figure out the number of ‘‘Looping Pairs’’ after each day’s all changes.

Note : (u,v) and (v,u) should not be counted twice.

Input

The first line of the input contains an integer T(1≤T≤15), denoting the number of test cases.

In each test case, there are 2 integers n,m(1≤n≤250,1≤m≤25000) in the first line, denoting the number of things and days.\par
For the next n lines, each line contains n integers gi,1,gi,2,…,gi,n(0≤gi,j≤1,gi,i=0), denoting the matrix g.

For the next m parts, there is an integer ki(1≤ki≤10) in the first line, denoting the number of changes happened on that day.

For the next ki lines, each line contains 2 integers u,v(1≤u,v≤n,u≠v), denoting a changed position in g.

It is guaranteed that each position will be changed at most once per day.

Output

For each day, print a single line containing an integer, denoting the number of ‘‘Looping Pairs’’ after that day’s all changes.

Sample Input

1
4 2
0010
1000
0000
0000
3
1 4
3 2
1 2
2
4 3
2 3

Sample Output

3
6

题解

题面真是有毒,大家可以自己去搜无码的原文。。。

题意大概是说求动态有向图上能互相到达的点对数。

那么我们就要维护 s c c scc scc及每个 s c c scc scc的大小,考虑到 T a r j a n \mathcal{Tarjan} Tarjan复杂度为 O ( n + m ) O(n+m) O(n+m)而且修改边的操作非常爆炸,无法处理多组询问,所以我们使用 K o s a r a j u \mathcal{Kosaraju} Kosaraju算法, K o s a r a j u \mathcal{Kosaraju} Kosaraju不需要遍历到所有的边,只需要遍历所有的点,又因为 n ≤ 150 n\le 150 n150,我们可以用邻接矩阵存图方便修改,复杂度 O ( n 2 ) O(n^2) O(n2)

貌似 K o s a r a j u \mathcal{Kosaraju} Kosaraju也没优化什么?我们还可以添加一些优化,显然我们可以将边表压进 B i t s e t \mathcal{Bitset} Bitset里,每次将边表 & v i s \&vis &vis v i s vis vis 1 1 1表示没有到达, 0 0 0表示已经到过),再用 _ _ b u i l t i n _ c t z ( ) \_\_builtin\_ctz() __builtin_ctz()就可以求出当前 B i t s e t \mathcal{Bitset} Bitset里没有到过的点,这样复杂度就变成了 O ( n 2 32 ) O(\frac{n^2}{32}) O(32n2),乖乖 A C \mathcal{AC} AC

代码
#include<bits/stdc++.h>
#define uint unsigned int
#define lg(x) __builtin_ctz(x)
using namespace std;
const int M=320,bit=32;
const uint inf=0xffffffff;
uint mmp[M][M/bit],mmp2[M][M/bit],vis[M/bit];
int cot[M],sta[M],top,T,n,m,ans,tot;
char ch[M];
void dfs1(int v){vis[v/bit]&=inf^(1<<v%bit);for(int i=0;i<=n/bit;++i)for(;mmp2[v][i]&vis[i];)dfs1(lg(mmp2[v][i]&vis[i])+i*bit);sta[++top]=v;}
void dfs2(int v){vis[v/bit]&=inf^(1<<v%bit),++cot[tot];for(int i=0;i<=n/bit;++i)for(;mmp[v][i]&vis[i];dfs2(lg(mmp[v][i]&vis[i])+i*bit));}
void work()
{
	int i;ans=tot=top=0;memset(cot,0,sizeof(cot));
	for(memset(vis,255,sizeof(vis)),i=1;i<=n;++i)if(vis[i/bit]>>i%bit&1)dfs1(i);
	for(memset(vis,255,sizeof(vis)),i=top;i>=1;--i)if(vis[sta[i]/bit]>>sta[i]%bit&1)++tot,dfs2(sta[i]);
	for(int i=1;i<=tot;++i)ans+=cot[i]*(cot[i]-1)/2;
	printf("%d\n",ans);
}
void reset(){memset(mmp,0,sizeof(mmp)),memset(mmp2,0,sizeof(mmp2));}
void in()
{
	scanf("%d%d",&n,&m);
	for(int i=1,j;i<=n;++i)for(scanf("%s",ch+1),j=1;j<=n;++j)if(ch[j]=='1')mmp[i][j/bit]|=1<<j%bit,mmp2[j][i/bit]|=1<<i%bit;
}
void ac(){for(int k,a,b;m--;work())for(scanf("%d",&k);k--;)scanf("%d%d",&a,&b),mmp[a][b/bit]^=1<<b%bit,mmp2[b][a/bit]^=1<<a%bit;}
int main(){for(scanf("%d",&T);T--;)reset(),in(),ac();}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值