bitset优化kosaraju,复杂度O(n^2/64),总复杂度O(n^4/64)。
#include <bits/stdc++.h>
using namespace std ;
typedef long long LL ;
typedef pair < int , int > pii ;
typedef unsigned long long ULL ;
#define clr( a , x ) memset ( a , x , sizeof a )
const int MAXN = 205 ;
const int BLOCK = 4 ;
int LIM ;
struct Node {
int v , x , y ;
Node () {}
Node ( int v , int x , int y ) : v ( v ) , x ( x ) , y ( y ) {}
bool operator < ( const Node& a ) const {
return v < a.v ;
}
} ;
struct Bitset {
ULL c[BLOCK] ;
bool none () {
for ( int i = 0 ; i < LIM ; ++ i ) {
if ( c[i] ) return 0 ;
}
return 1 ;
}
void set () {
for ( int i = 0 ; i < LIM ; ++ i ) {
c[i] = ~0ULL ;
}
}
void reset () {
for ( int i = 0 ; i < LIM ; ++ i ) {
c[i] = 0 ;
}
}
void flip ( int x ) {
c[x >> 6] ^= 1ULL << ( x & 63 ) ;
}
ULL& operator [] ( const int index ) {
return c[index] ;
}
} ;
Node a[MAXN * MAXN] ;
Bitset G[MAXN << 1] , V[MAXN << 1] , vis[2] ;
ULL pos[MAXN] , val[MAXN] ;
int scc[MAXN << 1] , scc_cnt ;
vector < int > S ;
int n , m ;
void add1 ( int x , int y ) {
G[x << 1].flip ( y ) ;
G[y << 1].flip ( x ) ;
V[x << 1 | 1].flip ( y ) ;
V[y << 1 | 1].flip ( x ) ;
}
void add2 ( int x , int y ) {
G[x << 1 | 1].flip ( y ) ;
G[y << 1 | 1].flip ( x ) ;
V[x << 1].flip ( y ) ;
V[y << 1].flip ( x ) ;
}
void dfs1 ( int u , int o ) {
vis[o].flip ( u ) ;
for ( int i = 0 ; i < LIM ; ++ i ) while ( 1 ) {
ULL v = vis[o ^ 1][i] & G[u << 1 | o][i] ;
if ( !v ) break ;
dfs1 ( i << 6 | __builtin_ctzll ( v ) , o ^ 1 ) ;
}
S.push_back ( u << 1 | o ) ;
}
void dfs2 ( int u , int o ) {
vis[o].flip ( u ) ;
scc[u << 1 | o] = scc_cnt ;
for ( int i = 0 ; i < LIM ; ++ i ) while ( 1 ) {
ULL v = vis[o ^ 1][i] & V[u << 1 | o][i] ;
if ( !v ) break ;
dfs2 ( i << 6 | __builtin_ctzll ( v ) , o ^ 1 ) ;
}
}
int check () {
S.clear () ;
vis[0].reset () ;
vis[1].reset () ;
for ( int i = 0 ; i < n ; ++ i ) {
vis[0][pos[i]] |= val[i] ;
vis[1][pos[i]] |= val[i] ;
}
for ( int o = 0 ; o < 1 ; ++ o ) {
for ( int i = 0 ; i < LIM ; ++ i ) while ( vis[o][i] ) {
dfs1 ( i << 6 | __builtin_ctzll ( vis[o][i] ) , o ) ;
}
}
for ( int i = 0 ; i < n ; ++ i ) {
vis[0][pos[i]] |= val[i] ;
vis[1][pos[i]] |= val[i] ;
}
scc_cnt = 0 ;
for ( int i = S.size () - 1 ; ~i ; -- i ) {
int o = S[i] & 1 , x = S[i] >> 1 ;
if ( vis[o][pos[x]] & val[x] ) {
++ scc_cnt ;
dfs2 ( x , o ) ;
}
}
for ( int i = 0 ; i < n ; ++ i ) {
if ( scc[i << 1] == scc[i << 1 | 1] ) {
return 0 ;
}
}
return 1 ;
}
void solve () {
m = 0 ;
LIM = ( n - 1 ) / 64 + 1 ;
for ( int i = 0 ; i < n ; ++ i ) {
G[i << 1].reset () ;
V[i << 1].reset () ;
G[i << 1 | 1].reset () ;
V[i << 1 | 1].reset () ;
pos[i] = i >> 6 ;
val[i] = 1ULL << ( i & 63 ) ;
}
for ( int i = 0 ; i < n ; ++ i ) {
for ( int j = i + 1 , x ; j < n ; ++ j ) {
scanf ( "%d" , &x ) ;
a[++ m] = Node ( x , i , j ) ;
add1 ( i , j ) ;
}
}
sort ( a + 1 , a + m + 1 ) ;
int ans = 2e9 + 10 ;
for ( int i = 0 , j = m ; i <= j ; ++ i ) {
while ( i && i <= j ) {
add1 ( a[i].x , a[i].y ) ;
if ( a[i].v != a[i + 1].v ) break ;
++ i ;
}
while ( i < j ) {
add2 ( a[j].x , a[j].y ) ;
if ( check () ) -- j ;
else {
add2 ( a[j].x , a[j].y ) ;
break ;
}
}
ans = min ( ans , a[i].v + a[j].v ) ;
}
printf ( "%d\n" , ans ) ;
}
int main () {
while ( ~scanf ( "%d" , &n ) ) solve () ;
return 0 ;
}