题意:给定一个矩阵A,其中A[i][j]>=0 && sigma[i][i]>0 问,是否存在K,使得B=A^K,其中B[i][j]>0
思路:矩阵乘法转图论. A^k大于0,代表所有元素直接是联通.
B=A^K 中 b[i][j]代表i到j长度为k的路条数
#include<bits/stdc++.h>
#define bug cout <<"bug"<<endl;
#define read(x) scanf("%d",&x)
using namespace std;
typedef long long ll;
const int MAX_N=2000+2;
const int MOD=1e9+7;
const int INF=0x3f3f3f3f;
vector <int> edge[MAX_N];
int n,cur,cnt,top,mp[MAX_N],DFN[MAX_N],LOW[MAX_N],s[MAX_N];
void tarjan(int u){
DFN[u]=LOW[u]=cur++;
s[++top]=u;
for(int i=0;i<(int)edge[u].size();i++){
int v=edge[u][i];
if(!DFN[v]){
tarjan(v);
LOW[u]=min(LOW[u],LOW[v]);
}
else if(DFN[v] && !mp[v]) LOW[u]=min(LOW[u],DFN[v]);
}
if(DFN[u]==LOW[u]){
int v=-1;
cnt++;
while(u!=v){
v=s[top--];
mp[v]=cnt;
// cout << v<<" ";
}
// puts("************");
}
}
int main(void){
read(n);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int x;read(x);
if(i==j) continue;
if(x>0) edge[i].push_back(j);
}
}
for(int i=1;i<=n;i++)
if(!DFN[i]) tarjan(i);
// cout << cnt << endl;
if(cnt==1) cout <<"YES"<<endl;
else cout <<"NO"<<endl;
return 0;
}