给你一个 n
个节点的 有向图 ,节点编号为 0
到 n - 1
,每个节点 至多 有一条出边。
有向图用大小为 n
下标从 0 开始的数组 edges
表示,表示节点 i
有一条有向边指向 edges[i]
。如果节点 i
没有出边,那么 edges[i] == -1
。
同时给你两个节点 node1
和 node2
。
请你返回一个从 node1
和 node2
都能到达节点的编号,使节点 node1
和节点 node2
到这个节点的距离 较大值最小化。如果有多个答案,请返回 最小 的节点编号。如果答案不存在,返回 -1
。
注意 edges
可能包含环。
示例 1:
输入:edges = [2,2,3,-1], node1 = 0, node2 = 1 输出:2 解释:从节点 0 到节点 2 的距离为 1 ,从节点 1 到节点 2 的距离为 1 。 两个距离的较大值为 1 。我们无法得到一个比 1 更小的较大值,所以我们返回节点 2 。
示例 2:
输入:edges = [1,2,-1], node1 = 0, node2 = 2 输出:2 解释:节点 0 到节点 2 的距离为 2 ,节点 2 到它自己的距离为 0 。 两个距离的较大值为 2 。我们无法得到一个比 2 更小的较大值,所以我们返回节点 2 。
提示:
n == edges.length
2 <= n <= 10^5
-1 <= edges[i] < n
edges[i] != i
0 <= node1, node2 < n
分析:题目提到每个点至多有一条出边,可以从某个点出发,一直沿着出边遍历,得到这个点可以到达的所有点,以及对应的距离。之后对比 node1 和 node2 能达到的点和距离,找到符合要求的点即可。
typedef struct node
{int pos,dis;
}node;int closestMeetingNode(int* edges, int edgesSize, int node1, int node2) {int t=1;int len1[edgesSize+5],len2[edgesSize+5],flag1[edgesSize+5],flag2[edgesSize+5];node num1[edgesSize+5],num2[edgesSize+5];memset(flag1,0,sizeof(flag1));memset(flag2,0,sizeof(flag2));flag1[node1]=1,num1[node1].dis=0,num1[node1].pos=node1;for(int i=node1;i<edgesSize;i=edges[i]){if(i==-1||edges[i]==-1)break;if(!flag1[edges[i]])num1[edges[i]].dis=t,num1[edges[i]].pos=edges[i],flag1[edges[i]]=1,t++;else break;}t=1;flag2[node2]=1,num2[node2].dis=0,num2[node2].pos=node2;for(int i=node2;i<edgesSize;i=edges[i]){if(i==-1||edges[i]==-1)break;if(!flag2[edges[i]])num2[edges[i]].dis=t,num2[edges[i]].pos=edges[i],flag2[edges[i]]=1,t++;else break;}int ans=-1,index=-1;for(int i=0;i<edgesSize;++i){if(flag1[i]&&flag1[i]==flag2[i]){if(ans==-1||ans>fmax(num1[i].dis,num2[i].dis))ans=fmax(num1[i].dis,num2[i].dis),index=num1[i].pos;else if(ans==fmax(num1[i].dis,num2[i].dis))index=fmin(index,num1[i].pos);}}return index;
}