题意:
给一个有向图的可达矩阵,求能构成这个可达矩阵的最小边数
貌似是强连通的。。 给我暴力dfs过了。。
主要是把所有没有用的边删去
对所有点都dfs,
例如dfs点i, 一直dfs,标记已经dfs过的点, 假设dfs到点u, u能到达v,但是v已经访问过,那么看v是不是u的祖先,如果是的话就不管,不是的话就把i到v的边删除
最后算边数就可以了
看起来很正确,其实不知道怎么证明╮(╯▽╰)╭ 莫名其妙的贪心就对了,不知道是数据水还是真的对了 = =!
#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
#include<string>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
using namespace std;
#define eps 1e-10
#define LL long long
#define inf 0x3f3f3f3f
const double PI = acos( -1.0 );
#define mxn 220
int a[mxn][mxn];
bool vis[mxn];
int p[mxn], n;
bool update;
void dfs( int u, int k ) {
for( int i = 1; i <= n; ++i ) {
if( !a[k][i] || i == k )
continue;
if( vis[i] ) {
if( !p[i] ) {
update = 1;
a[u][i] = 0;
}
continue;
}
vis[i] = 1;
p[i] = 1;
dfs( u, i );
p[i] = 0;
}
}
int main() {
// freopen( "tt.txt", "r", stdin );
while( scanf( "%d", &n ) != EOF ) {
for( int i = 1; i <= n; ++i )
for( int j = 1; j <= n; ++j ) {
scanf( "%d", &a[i][j] );
}
// while( 1 ) {
// update = 0;
for( int i = 1; i <= n; ++i ) {
memset( vis, 0, sizeof( vis ) );
vis[i] = 1;
p[i] = 1;
dfs( i, i );
}
// if( !update )
// break;
// }
int ans = 0;
for( int i = 1; i <= n; ++i )
for( int j = 1; j <= n; ++j )
if( a[i][j] && i != j )
ans ++;
printf( "%d\n", ans );
}
return 0;
}