882. 细分图中的可到达结点

从具有 0 到 N-1 的结点的无向图(“原始图”)开始,对一些边进行细分。

该图给出如下:edges[k] 是整数对 (i, j, n) 组成的列表,使 (i, j) 是原始图的边。

n 是该边上结点的总数

然后,将边 (i, j) 从原始图中删除,将 n 个新结点 (x_1, x_2, ..., x_n) 添加到原始图中,

将 n+1 条新边 (i, x_1), (x_1, x_2), (x_2, x_3), ..., (x_{n-1}, x_n), (x_n, j) 添加到原始图中。

现在,你将从原始图中的结点 0 处出发,并且每次移动,你都将沿着一条边行进。

返回最多 M 次移动可以达到的结点数。

 

示例 1:

输入:edges = [[0,1,10],[0,2,1],[1,2,2]], M = 6, N = 3
输出:13
解释:
在 M = 6 次移动之后在最终图中可到达的结点如下所示。

示例 2:

输入:edges = [[0,1,4],[1,2,6],[0,2,8],[1,3,1]], M = 10, N = 4
输出:23

 

提示:

  1. 0 <= edges.length <= 10000
  2. 0 <= edges[i][0] < edges[i][1] < N
  3. 不存在任何 i != j 情况下 edges[i][0] == edges[j][0] 且 edges[i][1] == edges[j][1].
  4. 原始图没有平行的边。
  5. 0 <= edges[i][2] <= 10000
  6. 0 <= M <= 10^9
  7. 1 <= N <= 3000

以下是思路的一种,但时间复杂度高,对大数据量会超时,建议使用邻接表排序后存储图:

当前代码如下:

class Solution {
public:
    void traverse(vector<vector<int>>& edges,vector<int> &points,int cur,int M,vector<int> &marks){
        //cout<<M<<" cur"<<cur<<endl;
        points[cur]=1;
        marks[cur]=1;
        int size=edges.size();
        //循环n个点
        for(int i=0;i<size;i++){
            if(edges[i][0]==cur){
                //能到达该点edges[i][1]
                if(M>=edges[i][2]+1)
                {
                    //该边节点满了
                    edges[i][3]=edges[i][2];
                    //还未访问过,则可以去访问
                    if(points[edges[i][1]]==0)
                    {
                        traverse(edges,points,edges[i][1],M-edges[i][2]-1,marks);
                    }
                    
                }//到达不了
                else{
                    edges[i][3]=max(M,edges[i][3]);
                }
            }else if(edges[i][1]==cur){
                if(M>=edges[i][2]+1)
                {
                    //该边中有n个节点
                    edges[i][4]=edges[i][2];
                    //还未访问过,则可以去访问
                    if(points[edges[i][0]]==0)
                    {
                        traverse(edges,points,edges[i][0],M-edges[i][2]-1,marks);
                    }
                }//到达不了
                else{
                    edges[i][4]=max(M,edges[i][4]);
                }
            }
           
        }
        points[cur]=0;
    }
    void intial(vector<vector<int>>& edges){
        int size=edges.size();
        for(int i=0;i<size;i++){
            edges[i].push_back(0);//从左往右
            edges[i].push_back(0);//从右往左
        }
    }
    int reachableNodes(vector<vector<int>>& edges, int M, int N) {
        intial(edges);
        vector<int> points(N);
        vector<int> marks(N);
        traverse(edges,points,0,M,marks);
        int result=0;
        for(vector<int> edge:edges){
            //cout<<edge[0]<<" "<<edge[1]<<" "<<edge[3]<<" "<<edge[4]<<endl;
            if(edge[3]+edge[4]>edge[2]){
                result+=edge[2];
            }else{
                result+=edge[3]+edge[4];
            }
        }
        for(int i=0;i<N;i++){
            if(marks[i]==1)
                result++;
        }
        return result;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值