HNU-离散数学-离散数学程序设计实验

离散数学程序设计实验(占期末比重1.5%)

希望能帮到HNUers,加油!

注释部分是原代码部分,如果帮到你了麻烦点个赞

#include <iostream>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <string.h>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <iomanip>
#include <algorithm>
#define INF 0x3f3f3f3f
#define N 100
using namespace std;
struct stree{
    int pointa,pointb,weight;
};
 
/* 修改点1:合并两个矩阵的输入 */
int inputadjaceedge(int a[][N],int b[][N],int *n,int *m)
{
    int i=0,j=0;
    printf("点数:");scanf("%d",n);fflush(stdin);
    printf("边数:");scanf("%d",m);fflush(stdin);
    printf("n=%d m=%d\n",*n,*m);
    printf("\n输入邻接矩阵的值:");
    for(i=0;i<*n;++i)
        for(j=0;j<*n;++j)
            scanf("%d",&a[i][j]);
    fflush(stdin);
    printf("\n输入关联矩阵的值:");
    for(i=0;i<*n;++i)
        for(j=0;j<*m;++j)
            scanf("%d",&b[i][j]);
    return 1;
}
 
//int inputadjace(int a[][N],int *n)
//{
//    int i=0,j=0;
//    printf("点数:");scanf("%d",n);fflush(stdin);
//    printf("\n输入邻接矩阵的值:");
//    for(i=0;i<*n;++i)
//        for(j=0;j<*n;++j)
//            scanf("%d",&a[i][j]);
//    fflush(stdin);
//    return 1;
//}
//
//int inputedge(int b[][N],int n,int *m)
//{
//    int i=0,j=0;
//    printf("边数:");scanf("%d",m);fflush(stdin);
//    printf("\n输入关联矩阵的值:");
//    for(i=0;i<n;++i)
//        for(j=0;j<*m;++j)
//            scanf("%d",&b[i][j]);
//    return 1;
//}
 
int print(int t[][N],int n,int m,char msg[])
{
    int i=0,j=0;
    printf("\n%s: \n",msg);
    for(i=0;i<n;++i)
    {
        for(j=0;j<m;++j)
            printf("%4d",t[i][j]);
        printf("\n");
    }
    return 1;
}
 
void caldegree(int a[][N],int n,int d[])
{
    int i=0,j=0;
    for(i=0;i<n;++i)
        d[i]=0;
    for(i=0;i<n;++i)
        for(j=0;j<n;++j)
            d[i]+=(a[i][j]==0?0:1);
}
 
int iseuler(int d[],int n)
{
    int n0dd=0,i=0;
    int i0dd1=0,j0dd2=0;printf("\n各点的度数:");
    for(i=0;i<n;++i)
        printf("%4d",d[i]);
    printf("\n");
    for(i=0;i<n;++i)
        if(d[i]%2==1)
        {
            n0dd++;
            if(i0dd1==0) i0dd1=i;
            else j0dd2=i;
        }
    if(n0dd==0)
        printf("\n存在Euler回路,即为Euler图\n");
    else if(n0dd==1)
        printf("\n存在Euler路,起点为%d 终点为%d\n",i0dd1,j0dd2);
    else
        printf("\n不存在Euler路与回路\n");
}
 
void ishamilton(int d[],int n)
{
    int ishp=1,ishg=1;
    int i=0,j=0;
    for(i=0;i<n;++i)
    {
        for(j=0;j<n;++j)
            if(d[i]+d[j]<n-1)
            {
                ishp=0;
                ishg=0;
                break;
            }
            else if(d[i]+d[j]<n)
            {
                ishg=0;
                break;
            }
            if(ishp==0) break;
    }
    if(ishg==1)
        printf("为Hamilton图\n");
    else if(ishp==1)
        printf("存在Hamilton路\n");
    else
        printf("不存在Hamilton路\n");
}
 
void caldegreeb(int b[][N],int n,int m,int d[])
{
    int i=0,j=0;
    for(i=0;i<n;++i)
        d[i]=0;
    for(i=0;i<n;++i)
        for(j=0;j<m;++j)
            if(b[i][j]!=0)
                d[i]++;
}
 
int warshall(int a[][N],int n)
{
    int p[N][N],i=0,j=0,k=0,n1count=0;
    for(i=0;i<n;++i)
        for(j=0;j<n;++j)
            p[i][j]=(a[i][j]>0?1:0);
    for(j=0;j<n;++j)
        for(i=0;i<n;++i)
            if(p[i][j]==1)
                for(k=0;k<n;++k)
                {
                    p[i][k]=p[i][k]+p[j][k];
                    if(p[i][k]>=1)
                        p[i][k]=1;
                }
    for(i=0;i<n;++i)
        for(j=0;j<n;++j)
            if(p[i][j]==1)
                for(k=0;k<n;++k)
                {
                    p[i][k]=p[i][k]+p[j][k];
                    if(p[i][k]>=1)
                        p[i][k]=1;
                }
    for(i=0;i<n;++i)
    {
        for(j=0;j<n;++j)
        {
            printf("%3d",p[i][j]);
            n1count+=p[i][j];
        }
        printf("\n");
    }
    if(n1count==n*n)
        printf("图连通\n");
    else
        printf("图不连通\n");
    return n1count;
}
 
int poweradjace(int a[][N],int n)
{
    int t[N][N],t2[N][N],aa[N][N],a0[N][N];
    char msg[100]="长度为",msgi[10];
    int i=0,j=0,k=0,m=0;
    for(i=0;i<n;++i)
        for(j=0;j<n;++j)
        {
            a0[i][j]=(a[i][j]>0?1:0);
            t[i][j]=a0[i][j];
            aa[i][j]=a0[i][j];
        }
    print(a0,n,n,strcat(msg,"长度为1的路情况即直接相连的情况"));
    for(i=2;i<=n;++i)
    {
        for(j=0;j<n;++j)
            for(k=0;k<n;++k)
            {
                t2[j][k]=0;
                for(m=0;m<n;++m)
                    t2[j][k]=t2[j][k]+t[j][m]*a0[m][k];
                aa[j][k]==aa[j][k]+t2[j][k];
            }
        for(j=0;j<n;++j)
            for(k=0;k<n;++k)
                t[j][k]=t2[j][k];
        itoa(i,msgi,10);
        strcpy(msg,"长度为");
        strcat(msg,msgi);
        strcat(msg,"的路情况");
        print(t2,n,n,msg);
    }
    print(aa,n,n,"汇总表");
    return 1;
}
 
int powellcolor(int a[][N],int n,int color[])
{
    int d[N],subindex[N],i=0,j=0,k=0,k0=0,itmp=0,thiscolor[N],m=0,nthiscolor=0;
    for(i=0;i<n;++i)
    {
        subindex[i]=i;
        color[i]=0;
    }
    caldegree(a,n,d);
    /* 修改点2:sort排序 */
    sort(d,d+n);
    sort(subindex,subindex+n);
//    for(i=0;i<n-1;++i)
//        for(j=0;j<n-1-i;++j)
//        {
//            if(d[j]<d[j+1])
//            {
//                swap(d[j],d[j+1]);
//                swap(subindex[j],subindex[j+1]);
//            }
//        }
    printf("排序后的结点度数:\n");
    for(i=0;i<n;++i)
        printf("%4d[%1d]",d[i],subindex[i]);
    itmp=0;
    for(i=0;i<n;++i)
    {
        for(j=0;j<n;++j)
            thiscolor[j]=0;
        nthiscolor=0;
        j=0;
        while(d[j]==-1&&j<n)
            j++;
        if(j>=n)
            break;
 
        k0=subindex[j];
        itmp++;
        color[k0]=itmp;
        d[j]=-1;
        thiscolor[nthiscolor]=k0;
        printf("\nk0=%d j=%d nthiscolor=%d itmp=%d\n",k0,j,nthiscolor,itmp);
 
        nthiscolor++;
        j++;
 
        while(1)
        {
            while(d[j]==-1&&j<n)
                j++;
            if(j==n)
                break;
            k=subindex[j];
            for(m=0;m<nthiscolor;++m)
                if(a[k][thiscolor[m]]>0)
                    break;
            printf("j=%d n=%d k=%d m=%d nthiscolor=%d\n",j,n,k,m,nthiscolor);
            if(m>=nthiscolor)
            {
                color[k]=itmp;
                thiscolor[m]=k;
                nthiscolor++;
                d[j]=-1;
            }
            j++;
        }
    }
    return 0;
}
 
int getedge(int a[][N],int n,stree t[])
{
    int i=0,j=0,nstree=0;
    for(i=0;i<n;++i)
        for(j=i;j<n;++j)
            if(a[i][j]>0)
            {
                t[nstree].pointa=i;
                t[nstree].pointb=j;
                t[nstree].weight=a[i][j];
                nstree++;
            }
    return nstree;
}
 
void printtree(stree t[],int nt)
{
    int i=0;
    for(i=0;i<nt;++i)
        printf("%d--%d(%d)",t[i].pointa,t[i].pointb,t[i].weight);
}
 
void sortedge(stree t[],int nt)
{
    stree t0;
    int i=0,j=0;
    for(i=0;i<nt-1;++i)
        for(j=0;j<nt-1-i;++j)
            if(t[j].weight>t[j+1].weight)
                /* 修改点3:中间元交换值改为swap */
                swap(t[j],t[j+1]);
}
 
int kruskal(stree t0[],int nt0,int n,stree t[])
{
    int i=0,j=0,k=0,nt=0,b[N][N],m=0,mtmp=0,ncount=0;
    t[nt]=t0[0];
    nt++;
    for(i=1;i<nt0;++i)
    {
        for(j=0;j<n;++j)
            for(k=0;k<nt0;++k)
                b[j][k]=0;
        for(j=0;j<nt;++j)
        {
            b[t[j].pointa][j]=1;
            b[t[j].pointb][j]=1;
        }
        b[t[i].pointa][j]=1;
        b[t[i].pointb][j]=1;
 
        printf("加入新边后的关联矩阵\n");
        for(j=0;j<n;++j)
        {
            for(k=0;k<=nt;++k)
                printf("%4d",b[j][k]);
            printf("\n");
        }
 
        for(k=0;k<=nt;++k)
        {
            for(j=k;j<n;++j)
                if(b[j][k]!=0)
                {
                    if(j>k)
                        for(m=0;m<=nt;++m)
                            swap(b[j][m],b[k][m]);
                    break;
                }
            for(j=k+1;j<n;++j)
                if(b[j][k]==1)
                    for(m=k;m<=nt;++m)
                        b[j][m]=b[j][m]-b[k][m]*b[j][k]/b[k][k];
        }
        printf("关联矩阵处理以后:\n");
        for(j=0;j<n;++j)
        {
            for(k=0;k<=nt;++k)
                printf("%4d",b[j][k]);
            printf("\n");
        }
        ncount=0;
        for(k=0;k<=nt;++k)
            if(b[k][k]!=0)
                ncount++;
        if(ncount==nt+1)
        {
            t[nt]=t0[i];
            nt++;
            if(nt==n-1)
                break;
        }
    }
    return nt;
}
 
int prim(stree t0[],int nt0,int n,stree t[])
{
    int i=0,j=0,k=0,nt=0,b[N][N],m=0,mtmp=0,ncount=0;
    int u[N],mdis=0,idis=0,jtree=0,ntree=0;
 
    u[nt]=0;
    printf("u[%d]=%d\n",nt,u[nt]);
    nt++;
    while(nt<n)
    {
        mdis=999999;
        idis=-1;
        for(i=0;i<nt;++i)
        {
            k=u[i];
            for(j=0;j<nt0;++j)
            {
                if(t0[j].pointa==k)
                    if(mdis>t0[j].weight)
                    {
                        mdis=t0[j].weight;
                        idis=t0[j].pointb;
                        jtree=j;
                    }
                else if(t0[j].pointb==k)
                    if(mdis>t0[j].weight)
                    {
                        mdis=t0[j].weight;
                        idis=t0[j].pointa;
                        jtree=j;
                    }
            }
        }
        u[nt]=idis;
        t[ntree]=t0[jtree];
        t0[jtree].weight=999999;
        printf("nt=%d u[%d]=%d ntree=%d jtree=%d\n",nt,nt,u[nt],ntree,jtree);
        ntree++;
        nt++;
    }
    return ntree;
}
 
int main()
{
	stree st0[N],st1[N];
	int A[N][N],B[N][N],D[N],color[N];
	int i=0,j=0,n=0,m=0;
	int nchoice,nt0=0,nt=0;
    /* 修改点4:优化交互 */
	bool flag1=false;
	while(1)
    {
        printf("\n===========================\n");
        if(!flag1)
            printf("1.输入邻接矩阵及关联矩阵\n");
        if(flag1)
        {
            printf("2.邻接矩阵求每点度数及短短图形性质\n3.关联矩阵求每点度数及判断图形性质\n4.用warshall算法判断是否连通\n");
            printf("5.计算A,A^2,A^3,...\n6.用Powell染色算法对结点染色\n");
            printf("7.用kruskal求最小生成树\n8.用prim求最小生成树\n");
        }
 
        printf("\n===========================\n");
        printf("您的选择(输入0结束):\n");
        
        /* 修改点5:判断输入是否合法 */
        while(scanf("%d",&nchoice))
            if((nchoice>=0&&nchoice<=8)) break;
            else printf("请重新输入\n");
        //scanf("%d",&nchoice);
        fflush(stdin);
        if(nchoice==0) break;
        switch(nchoice)
        {
            case 1:
                {
                    inputadjaceedge(A,B,&n,&m);
                    print(A,n,n,"邻接矩阵");
                    flag1=true;
                    break;
                }
//            case 11:
//                {
//                    inputedge(B,n,&m);
//                    print(B,n,m,"关联矩阵");
//                    flag11=true;
//                    break;
//                }
            case 2:
                {
                    caldegree(A,n,D);
                    iseuler(D,n);
                    ishamilton(D,n);
                    break;
                }
            case 3:
                {
                    caldegreeb(B,n,m,D);
                    iseuler(D,n);
                    ishamilton(D,n);
                    break;
                }
            case 4:
                {
                    warshall(A,n);
                    break;
                }
            case 5:
                {
                    poweradjace(A,n);
                    break;
                }
            case 6:
                {
                    powellcolor(A,n,color);
                    printf("各点的颜色:\n");
                    for(i=0;i<n;++i)
                        printf("%2d",color[i]);
                    break;
                }
            case 7:
                {
                    nt0=getedge(A,n,st0);
                    printtree(st0,nt0);
                    sortedge(st0,nt0);
                    printtree(st0,nt0);
                    nt=kruskal(st0,nt0,n,st1);
                    printtree(st1,nt);
                    break;
                }
            case 8:
                {
                    nt0=getedge(A,n,st0);
                    printtree(st0,nt0);
                    sortedge(st0,nt0);
                    printtree(st0,nt0);
                    nt=prim(st0,nt0,n,st1);
                    printtree(st1,nt);
                    break;
                }
        }
    }
 
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值