离散数学实验-01 可简单图化,连通图和欧拉图的判断(利用Fleury算法输出欧拉回路)

离散数学的实验

实验要求

  1. 给定一非负整数序列(例如:(4,2,2,2,2))。
  2. 判断此非负整数序列是否是可图化的,是否是可简单图化的。
  3. 如果是可简单图化的,根据Havel定理过程求出对应的简单图,并输出此简单图的相邻矩阵(默认第i行对应顶点vi)。
  4. 判断此简单图是否是连通的。
  5. 如果是连通图,判断此图是否是欧拉图。如果是欧拉图,请输出一条欧拉回路(输出形式如:v2->v1->v5->v3->v4->v5->v2)。

难度不太大,但是好多同学没有学过图的数据结构,邻接表 ,邻接矩阵啥的,所以这个地方把代码放上来供大家学习
说一下基本思路吧

基本流程
图化直接用定理度数列之和为偶数(握手定理)
简单图用Havel定理判断顺便建表
连通图我刚开始用的并查集,但是并查集判断是否联通之后就废了,但是后面发现找欧拉回路时要用dfs判断连通块中点的数量,所以后面索性改成dfs判断连通了(应该早点把全局思路打开了再写代码了,浪费了一点点时间)
然后是否是欧拉图判断一下度数列是否都是偶数就行
找欧拉回路用fleury算法,找的时候判断边是否是桥的话用dfs判断一下连通块中点的数量

Java代码放上

class Node implements Comparable<Node> {
    int degree;
    int idx;
    int pre;
    public Node(int x,int y,int z)
    {
        this.idx=x;
        this.degree=y;
        this.pre=z;
    }

    @Override
    public int compareTo(Node o) {
        return Integer.compare(o.degree,this.degree);
    }
}



public class Exp {
    static int N=110;
    static int M=1010;
    static int n;
    static int father;
    static int edgeIdx=0;
    static Map<Integer,List<Node>> map=new HashMap<>();
    static int[][] Matrix=new int[N][N];
    static Node[] nodes=new Node[N];
    static Node[] nodeCopy=new Node[N];
    static int[][] edge=new int[N][M];
    public static void main(String[] args) throws IOException {
        BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
        String[] param=reader.readLine().split(" ");
        n= param.length;
        for(int i=0;i<param.length;i++)//初始化度数列
        {
            nodes[i]=new Node(i,Integer.parseInt(param[i]),i);
        }
        for(int i=0;i<n;i++)
        {
            nodeCopy[i]=new Node(nodes[i].idx,nodes[i].degree,i);
        }
        if(!isGraph(nodes))
            System.err.println("不可图化QAQ");
        else
        {
            System.out.println("可图化");
            if(isSimple(nodes))
            {
                System.out.println("可简单图化");
                showMatrix();
                if(isConnect())
                {
                    System.out.println("该图为连通图");
                    if(isEur())
                    {
                        System.out.println("是欧拉图哦!");
                        System.out.println("输出欧拉回路");
                        Fleury(0);
                    }
                    else
                    {
                        System.out.println("不是欧拉图哦!");
                    }
                }
                else
                {
                    System.out.println("不是连通图哦QAQ");
                }
            }
            else
            {
                System.out.println("不可简单图化");
            }
        }
    }
    static void Fleury(int x)//找欧拉回路
    {

        for(int i=0;i<edgeIdx;i++)
        {
            if(Matrix[x][i]==1) {
                int nextIdx = i;
                if (isNextEdge(x, nextIdx)) {
                    System.out.print(x + "->" + nextIdx + " ");
                    removeEdge(x, nextIdx);
                    Fleury(nextIdx);
                }
            }
        }
        System.out.println();
        return;
    }
    static void removeEdge(int x,int y)//删边
    {
        Matrix[x][y]=Matrix[y][x]=0;
    }
    static void addEdge(int x,int y)
    {
        Matrix[x][y]=Matrix[y][x]=1;
    }
    static boolean isNextEdge(int x,int y)//判断是否是桥
    {
        int countEdge=0;
        for(int i=0;i<edgeIdx;i++)
        {
            if(Matrix[y][i]==1)
            {
                countEdge++;
            }
        }
        if(countEdge>0)return true;
        else
        {
            boolean[][] visited=new boolean[n][edgeIdx];
            int count1=dfs(x,visited);
            removeEdge(x,y);
            visited=new boolean[n][edgeIdx];
            int count2=dfs(x,visited);
            if(count1-count2==0)
                return true;
            else
                return false;
        }
    }
    static int dfs(int x,boolean[][] v)//搜索点所在连通块中点的数量
    {
        int count=0;
        for(int i=0;i<edgeIdx;i++)
        {
            if(Matrix[x][i]==1&&Matrix[i][x]==1&&!v[x][i]&&!v[i][x])
            {
                v[x][i]= v[i][x]=true;
                count++;
                count+=dfs(i,v);
            }
        }
        return count;
    }
    static boolean isEur()//判断是否是欧拉图
    {
        for(int i=0;i<n;i++)
        {
            if(nodeCopy[i].degree%2!=0)
                return false;
        }
        return true;
    }
    static void showMatrix()//打印相邻矩阵
    {
        for(int i=0;i<n;i++) {
            for (int j = 0; j < n; j++) {
                System.out.print(Matrix[i][j] + " ");
            }
            System.out.println();
        }
    }
    static boolean isSimple(Node[] a)//判断是否可简单图化
    {

        if(a[0].degree>n)
            return false;
        else
        {
            return Havel();
        }
    }
    static boolean Havel()//用Havel搞一个简单图
    {
        int l=0;
        int r=n-1;
        int count=0;
        Arrays.sort(nodes,count,n);
        nodes[0].pre=nodes[0].idx;
        father=nodes[0].pre;
        while(count<n)
        {
            Arrays.sort(nodes,count,n);
            Node start=nodes[count];
            l=count;
            if(start.degree==0)
                break;
            for(int size=nodes[l].degree;l<(count+size);)
            {
                l++;
                if(l>=n)
                    return false;
                else {
                    int idx=nodes[l].idx;
                    nodes[l].pre = start.idx;
                    nodes[l].degree--;
                    if (addList(idx)) {
                        map.get(idx).add(start);
                        Matrix[idx][start.idx] = 1;
                        edge[idx][edgeIdx]=1;
                        edge[start.idx][edgeIdx]=1;
                        edgeIdx++;
                    }
                    if (addList(start.idx)) {
                        map.get(start.idx).add(nodes[l]);
                        Matrix[start.idx][idx] = 1;
                    }
                }
            }
            count++;
        }
        if(!checkSimple(nodes)) {
            System.err.println("不可简单图化");
            return false;
        }
        else
        {
            return true;
        }

    }
    static boolean isConnect()//判断是否连通
    {
        boolean[][] visited=new boolean[n][edgeIdx];
        int count1=dfs(0,visited);
        for(int i=1;i<n;i++)
        {
           visited=new boolean[n][edgeIdx];
           int count=dfs(i,visited);
           if(count!=count1)
               return false;
        }
        return true;
    }
    static int find(int a)//并查集的find后面改了没有用到
    {
        if(nodes[a].pre!=nodes[a].idx)
        {
            nodes[a].pre=find(nodes[a].pre);
        }
        return nodes[a].pre;
    }
    static boolean addList(int a)//建领接表,其实没有用到,后面换成邻接矩阵了
    {
        if(map.get(a)!=null)
            return true;
        else
        {
            List<Node> list=new ArrayList<Node>();
            map.put(a,list);
            return true;
        }

    }
    static boolean checkSimple(Node[] a)//是否简单 
    {
        for(int i=0;i<n;i++)
        {
            if(a[i].degree<0)
                return false;
        }
        return true;
    }
    static boolean isGraph(Node[] a)//是否可图化 
    {
        int s=sum(a);
        if(s%2==0)
            return true;
        else
            return false;
    }
    static int sum(Node[] a)//求度数列和
    {
        int s=0;
        for(int i=0;i<n;i++)
        {
            s+=a[i].degree;
        }
        return s;
    }
}
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值