poj3713 Transferring Sylla (java实现)

问题描述

给一个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;
        }
    }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值