小猿在加载一个网页,这个网页共需要N个相关资源,这些资源之间有一些依赖关系。如果这些资源中存在循环依赖,我们认为这个网页不能加载成功,否则可以加载成功。存在循环依赖是指,这些资源中存在资源X,X依赖的资源Y直接或间接依赖于X。判断一下这个网页能否加载成功。
输入描述:第一行输入T(T ≤ 10),表示输入T组数据。每组数据第1行,输入一个数N(1 ≤ N ≤ 500)表示该组case有编号为1~N的N项资源。每组数据第2到 N+1 行,输入一个 N*N 的零一矩阵。矩阵第 i 行第 j 列数字为 a[i][j] 表示编号为 i 的资源是否依赖于编号为 j 的资源,1表示依赖,0表示不依赖。数据保证a[i][i] = 0。
输出描述:输出包含T行,每行输出对应每组case中是否存在循环依赖。存在输出1,不存在输出0。
循环依赖可以这样理解,从i开始查找,每次查找的时候,将flag[i]=1;然后查找i依赖的值(即判断arr[i][j]==1是否存在),若不存在,则说明i不依赖于任何值,flag[i]==2,b,并返回true表明包含i值的不存在循环依赖,继续判断i++的情况;若存在,则i依赖于j,然后继续按照上述方法查找j依赖的值, 直到遇到下一个查找的值flag[j]==1,说明值j已经是这个依赖关系中的某一个,则存在循环依赖。
比如0-2 2-3 3-0(0依赖2,2依赖3,3依赖0)首先i=0传入dfs,设置flag[0]=1;然后遍历判断arr[0][j]==1,找到了j=2(因为0依赖2,所以数组对应位置为1),flag[2]不等于1,传入2到dfs函数,查找2的依赖值,设置flag[2]=1,然后遍历判断arr[2][j]==1,找到了j=3,flag[3]不等于1,传入3到dfs函数,查找3的依赖值,设置flag[3]=1,然后遍历判断arr[3][j]==1,找到了j=0,flag[0]等于1,则存在循环依赖,dfs函数返回false。
详细代码如下:
#include <iostream>
#include <vector>
using namespace std;
bool dfs( vector<vector<int>>& sour, vector<int>& flag, int n, int i )
{
//从值i开始查找,若是sour[i][j]==1,说明值i依赖于j,则递归调用继续查找值j依赖的值,
//知道查找的值flag[i]==1,说明查找到之前已经查找过的值了,则存在循环依赖
flag[i] = 1;
for ( int j = 0; j < n; ++j )
{
if ( sour[i][j] == 1 )
{
if ( flag[j] == 1 || !dfs(sour,flag,n,j) )
return false;
}
}
flag[i] = 2;
return true;
}
int main()
{
int times;
cin >> times;
for ( int i = 0; i < times; ++i )
{
int size;
cin >> size;
vector<vector<int>> sour(size,vector<int>(size));
vector<int> flag(size,0); //flag[i]表示值i是否依赖其他值
for ( int j = 0; j < size; ++j )
{
for ( int k = 0; k < size; ++k )
{
cin >> sour[j][k];
}
}
bool isGood = true;
for ( int i = 0; i < size; ++i )
{
if ( flag[i] != 2 && !dfs(sour,flag,size,i) )
//flag[i]==2说明i不依赖任何值,不会以i为关系构成循环依赖,
//dfs也没有必要继续判断,直接跳过循环体,判断下一个i
//flag[i]!=2则需要判断后面条件,若dfs返回false,则存在循环依赖。
{
isGood = false;
break;
}
}
if (isGood)
cout << 0;
else
cout << 1;
if ( i != times - 1 )
cout << endl;
}
return 0;
}