1. 程式人生 > >[BZOJ2208][Jsoi2010]連通數 暴力枚舉

[BZOJ2208][Jsoi2010]連通數 暴力枚舉

數組 sizeof tput efi pac cor jpg its search

Description

技術分享圖片

Input

輸入數據第一行是圖頂點的數量,一個正整數N。 接下來N行,每行N個字符。第i行第j列的1表示頂點i到j有邊,0則表示無邊。

Output

輸出一行一個整數,表示該圖的連通數。

Sample Input

3
010
001
100

Sample Output

9

HINT

對於100%的數據,N不超過2000。

Source

第一輪

Solution

好好的暴力不寫去寫什麽算法

雖然我也是學算法學傻了的,前兩天看到一道題說這不是莫隊裸題嗎,然後其實前綴和就行了

做法1:$tarjan$縮點+拓撲

做法2:$floyd$傳遞閉包

做法3:暴力$dfs$

因為我這人比較菜所以就寫做法3了

對於每個點直接開一個$vis$數組判斷有沒有到達過就可以了

比tarjan短多了

#include <bits/stdc++.h>

using namespace std ;

#define N 2010
#define ll long long 

int n , head[ N ] , cnt , vis[ N ] ;  
struct node {
    int to , nxt ;
}e[ N * N ] ;

void ins( int u , int
v ) { e[ ++ cnt ].to = v ; e[ cnt ].nxt = head[ u ] ; head[ u ] = cnt ; } ll find( int u ) { ll ans = 1 ; vis[ u ] = 1 ; for( int i = head[ u ] ; i ; i = e[ i ].nxt ) { if( vis[ e[ i ].to ] ) continue ; ans += find( e[ i ].to ) ; } return
ans ; } int main() { scanf( "%d" , &n ) ; for( int i = 1 ; i <= n ; i ++ ) { char ch[ 2010 ] ; scanf( "%s" , ch + 1 ) ; for( int j = 1 ; j <= n ; j ++ ) { if( ch[ j ] == 1 ) { ins( i , j ) ; } } } ll ans = 0 ; for( int i = 1 ; i <= n ; i ++ ) { memset( vis , 0 ,sizeof( vis ) ) ; ans += find( i ) ; // printf( "Case #%d : %d\n" , i , ans - t ) ; } printf( "%lld\n" , ans ) ; return 0 ; }

[BZOJ2208][Jsoi2010]連通數 暴力枚舉