題目大意
給定
有
Data Constraint
題解
對於一個詢問,如果求出所有的強連通分量大小的話,問題就變得很簡單了。
用Kosaraju算法求強連通分量,然後就可以很方便的用bitset保存邊集優化轉移。
對於原邊集可以先分塊,然後維護一個邊集的ST表。每個詢問就可以很方便的取出對應的邊集了。
SRC
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<cmath>
using namespace std ;
#define N 300000 + 10
#define M 250 + 10
#define K 650 + 10
const int MAXN = 11 ;
struct Edge {
int u , v ;
} E[N] ;
bitset < M > vis , tp ;
bitset < M > ret[M] , trans[M] , retrans[M] ;
bitset < M > f[2][K][MAXN][M] ;
int S[M] , Tab[N] ;
int Belong[N] ;
int n , m , Q ;
int Size , Cnt , Block ;
void Merge( int type , int i1 , int i2 , int j ) {
for (int x = 1 ; x <= n ; x ++ ) {
if ( i2 > Cnt ) ret[x] = f[type][i1][j][x] ;
else ret[x] = f[type][i1][j][x] | f[type][i2][j][x] ;
}
}
void Get( int l , int r ) {
int k = Tab[r-l+1] ;
Merge( 0 , l , r - (1 << k) + 1 , k ) ;
for (int x = 1 ; x <= n ; x ++ ) trans[x] = ret[x] ;
Merge( 1 , l , r - (1 << k) + 1 , k ) ;
for (int x = 1 ; x <= n ; x ++ ) retrans[x] = ret[x] ;
}
void DFS( int x ) {
vis[x] = 0 ;
while ( 1 ) {
tp = trans[x] & vis ;
if ( !tp.any() ) break ;
int Son = tp._Find_next(-1) ;
DFS( Son ) ;
}
S[++S[0]] = x ;
}
void ReDFS( int x ) {
vis[x] = 0 ;
Size ++ ;
while ( 1 ) {
tp = retrans[x] & vis ;
if ( !tp.any() ) break ;
int Son = tp._Find_next(-1) ;
ReDFS( Son ) ;
}
}
int main() {
freopen( "friend.in" , "r" , stdin ) ;
freopen( "friend.out" , "w" , stdout ) ;
scanf( "%d%d%d" , &n , &m , &Q ) ;
Block = sqrt(m) ;
for (int i = 1 ; i <= m ; i ++ ) {
Belong[i] = i / Block + ( i % Block != 0 ) ;
scanf( "%d%d" , &E[i].u , &E[i].v ) ;
}
Cnt = Belong[m] ;
Tab[1] = 0 ;
for (int i = 2 ; i <= Cnt ; i ++ ) Tab[i] = Tab[i/2] + 1 ;
for (int i = 1 ; i <= Cnt ; i ++ ) {
for (int j = (i - 1) * Block + 1 ; j <= i * Block ; j ++ ) {
f[0][i][0][E[j].u][E[j].v] = 1 ;
f[1][i][0][E[j].v][E[j].u] = 1 ;
}
}
for (int type = 0 ; type <= 1 ; type ++ ) {
for (int j = 1 ; j < MAXN ; j ++ ) {
for (int i = 1 ; i <= Cnt ; i ++ ) {
Merge( type , i , i + (1 << (j - 1)) , j - 1 ) ;
for (int x = 1 ; x <= n ; x ++ ) f[type][i][j][x] = ret[x] ;
}
}
}
for (int i = 1 ; i <= Q ; i ++ ) {
int l , r ;
scanf( "%d%d" , &l , &r ) ;
if ( Belong[l] != Belong[r] ) {
for (int x = 1 ; x <= n ; x ++ ) trans[x].reset() , retrans[x].reset() ;
int lx = Belong[l-1] != Belong[l] ? Belong[l] : Belong[l] + 1 ;
int rx = Belong[r+1] != Belong[r] ? Belong[r] : Belong[r] - 1 ;
if ( lx <= rx ) Get( lx , rx ) ;
for (int j = l ; j <= (lx - 1) * Block ; j ++ ) {
trans[E[j].u][E[j].v] = 1 ;
retrans[E[j].v][E[j].u] = 1 ;
}
for (int j = rx * Block + 1 ; j <= r ; j ++ ) {
trans[E[j].u][E[j].v] = 1 ;
retrans[E[j].v][E[j].u] = 1 ;
}
} else {
for (int x = 1 ; x <= n ; x ++ ) trans[x].reset() , retrans[x].reset() ;
for (int j = l ; j <= r ; j ++ ) {
trans[E[j].u][E[j].v] = 1 ;
retrans[E[j].v][E[j].u] = 1 ;
}
}
S[0] = 0 ;
vis.set() ;
for (int x = 1 ; x <= n ; x ++ ) {
if ( vis[x] == 0 ) continue ;
DFS(x) ;
}
vis.set() ;
int ans = 0 ;
while ( S[0] ) {
if ( vis[S[S[0]]] == 0 ) { S[0] -- ; continue ; }
Size = 0 ;
ReDFS( S[S[0]] ) ;
ans += Size * (Size - 1) / 2 ;
S[0] -- ;
}
printf( "%d\n" , ans ) ;
}
return 0 ;
}
以上.