离散数学的实验
实验要求
- 给定一非负整数序列(例如:(4,2,2,2,2))。
- 判断此非负整数序列是否是可图化的,是否是可简单图化的。
- 如果是可简单图化的,根据Havel定理过程求出对应的简单图,并输出此简单图的相邻矩阵(默认第i行对应顶点vi)。
- 判断此简单图是否是连通的。
- 如果是连通图,判断此图是否是欧拉图。如果是欧拉图,请输出一条欧拉回路(输出形式如: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;
}
}