问题描述
我有一个有向图,有 N 个顶点,从 1 到 N,还有 N 个边。边由数组 A & B 表示。要求是查找图是否为循环。如果可以从某个顶点开始,并沿着提供的边,访问所有其他边并返回到起点,则图是一个循环。
示例:
A={1,3,2,4}
B ={4,1,2}
2->3->1->4
^ |
|--------|
当我们有一个循环时返回 true。
示例:
A={1,4}
B ={2,4,3}
1 <-> 2
3 <-> 4
返回 false,因为我们没有循环。该图有 2 个不相交的循环,每个循环的长度为 2
现在我可以创建一个以键为节点、以值为连接节点的映射。
static boolean process(int[] A,int[] B,int n) {
Map<Integer,List<Integer>> map = new HashMap<>();
for (int i = 0; i < A.length; i++) {
int a = A[i];
int b = B[i];
List<Integer> list = map.getOrDefault(a,new ArrayList<>());
list.add(b);
map.put(a,list);
}
System.out.println(map);
}
现在如何识别周期?
解决方法
您可以使用一个简单的 int
数组来保存您的地图。然后,正如 Vincent van der Weele 在他的评论中所说,这只是计算包含第一个元素的循环的长度并检查它是否等于图的大小的问题。
static boolean process(int[] a,int[] b,int n) {
int[] map = new int[n];
for(int i=0; i<n; i++) {
map[a[i]-1] = b[i]-1;
}
int len = 0;
int curr = 0;
do
{
curr = map[curr];
len += 1;
}
while (curr != 0);
return len == n;
}
测试:
System.out.println(process(new int[] {1,3,2,4},new int[] {4,1,2},4));
System.out.println(process(new int[] {1,new int[] {2,4,3},4));
输出:
true
false
,
我会遍历边直到算法到达起始顶点或比生成的边更多的步数。
static boolean walk(int[] a,int[] b) {
int len = 0;
int indexFrom = 1;
do
{
int indexTo = a[indexFrom - 1];
indexFrom = b[indexTo - 1];
len++;
}
while (indexFrom != 1 && len <= a.length);
return len == a.length;
}
public static void main(String []args){
System.out.println(walk(new int[] {1,2}));
System.out.println(walk(new int[] {1,3}));
System.out.println(walk(new int[] {1,new int[] {3,3}));
}