从具有 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 次移动之后在最终图中可到达的结点如下所示。

JAVA程序设计:细分图中的可到达结点(LeetCode:882)_广搜

示例 2:

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

提示:

0 <= edges.length <= 10000
0 <= edges[i][0] < edges[i][1] < N
不存在任何 i != j 情况下 edges[i][0] == edges[j][0] 且 edges[i][1] == edges[j][1].
原始图没有平行的边。
0 <= edges[i][2] <= 10000
0 <= M <= 10^9
1 <= N <= 3000
可到达结点是可以从结点 0 开始使用最多 M 次移动到达的结点。

思路:广搜跑最短路,我们将两点之间新结点的数量当做权值,我们每次走这条边时需要记下从左往右走和从右往左走已经标记了几个新结点,除此之外就是裸的最短路了,因为我们能走的步数最多为m,所以我们需要尽可能的遍历更多的点(也就是到其它点的最短路)。

class Solution {
	
	class node{
		int v,val;
		public node(int v,int val) {
			this.v=v;
			this.val=val;
		}
	}
	
	private int ans;
	private int[] road;
	private boolean[] used;
	private List<List<node>> list; 
	private int[][] dis;
	
    public int reachableNodes(int[][] edges, int M, int N) {

    	road=new int[N];
    	used=new boolean[N];
    	dis=new int[N][N];
    	list=new ArrayList<>();
    	Queue<node> q=new LinkedList<>();
    	 
    	for(int i=0;i<N;i++) {
    		used[i]=false;
    		road[i]=30000005;
    		list.add(new ArrayList<>());
    	}
    	for(int i=0;i<edges.length;i++) {
    		list.get(edges[i][0]).add(new node(edges[i][1],edges[i][2]));
    		list.get(edges[i][1]).add(new node(edges[i][0],edges[i][2]));
    	}
    	
    	ans=1;
    	road[0]=0;
    	used[0]=true;
    	q.add(new node(0,M));
    	
    	while(!q.isEmpty()) {
    		node now=q.poll();
    		if(now.val<=0) continue;
    		for(int i=0;i<list.get(now.v).size();i++) {
        		int v=list.get(now.v).get(i).v;
        		int num=list.get(now.v).get(i).val;
        		
        		int val=num+dis[v][now.v];
        		
        		if(now.val<=val) {
        			ans+=Math.max(0, now.val+dis[now.v][v]);
        			dis[now.v][v]=Math.min(dis[now.v][v], -now.val);
        		}
        		else {
    	    		ans+=Math.max(0, val+dis[now.v][v]);
    	    		dis[now.v][v]=Math.min(dis[now.v][v], -val);
    	    		if(now.val-num-1<0) continue;
    	    		if(!used[v]) ans++;
    	    		used[v]=true; 
    	    		if(road[v]>=road[now.v]+num+1) {
    	    			road[v]=road[now.v]+num+1;
    	    			q.add(new node(v,now.val-num-1));
    	    		}
        		}
        		
        		if(dis[now.v][v]+dis[v][now.v]<=-num)
        			dis[now.v][v]=dis[v][now.v]=-num;
        	}
    	}
    	
    	return ans;
    }
}