问题描述
给一个N个节点的图,要求任意两个顶点之间至少有3条独立的路径,判断所给的图是否满足该条件。
问题分析
所有点之间都有3条独立的路径就表示点3连通图,如果任意删掉1个点,图仍然是双连通图,那么原图是3连通图。双连通图可以根据tarjan算法判断。
算法实现
import java.io.*;
import java.util.Arrays;
import static java.lang.Math.min;
public class Main {
StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter out = new PrintWriter(System.out);
int read() throws IOException {
in.nextToken();
return (int) in.nval;
}
String readString() throws IOException {
in.nextToken();
return in.sval;
}
public static void main(String[] args) throws IOException {
new Main().solve();
}
int MAXN = 505;
int N, M;
Edge[] head = new Edge[MAXN];
private void solve() throws IOException {
while ((N = read()) != 0){
M = read();
Arrays.fill(head, null);
for (int i = 0; i < M; i++) {
int u = read();
int v = read();
addEdge(u, v);
}
boolean flag = true;
out:
for (int i = 0; i < N; i++) {
Arrays.fill(dfn, -1);
Arrays.fill(low, -1);
cnt = 0;
cutPointNum = 0;
tarjan((i+1) % N, -1, (i+1) % N, i);
if (cnt < N-1 || cutPointNum > 0){
// 不连通或者存在割点
flag = false;
break out;
}
}
out.println(flag ? "YES" : "NO");
}
out.flush();
}
int[] dfn = new int[MAXN];
int[] low = new int[MAXN];
int cnt = 0;
int cutPointNum = 0;
private void tarjan(int v, int fa, int root, int x){
dfn[v] = low[v] = cnt++;
int children = 0;
for (Edge e = head[v]; e != null; e = e.next){
if (e.to == fa || e.to == x){
// 父节点或者删除节点
continue;
}
if (dfn[e.to] == -1){
children++;
tarjan(e.to, v, root, x);
low[v] = min(low[v], low[e.to]);
// 割点
if (v == root && children>1 || v != root && low[e.to] >= dfn[v]){
cutPointNum++;
}
}else {
low[v] = min(low[v], dfn[e.to]);
}
}
}
private void addEdge(int u, int v) {
head[u] = new Edge(u, v, head[u]);
head[v] = new Edge(v, u, head[v]);
}
class Edge{
int from, to;
Edge next;
public Edge(int from, int to, Edge next) {
this.from = from;
this.to = to;
this.next = next;
}
}
}