循环依赖(猿辅导试题)

小猿在加载一个网页,这个网页共需要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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值