关于一些图论的算法

     如何编程求有向图的单向连通分支。

     如果在一个有向图中取一组顶点,满足:

 1.其中,任意甲乙两点间,一定存在其中一点至另一点的通路(即存在甲至乙或乙至甲的通路)

2.如果再向该组点中加入该图的其他点后,则一定存在两点间没有任何单向连通的通路。

则称这一组点构成该有向图的一个单向连通分支。

#include <stdio.h>

#define MAX_VEX_NUM 20

/*图的结构*/
typedef struct graph{
 int arcs[MAX_VEX_NUM][MAX_VEX_NUM];  /*邻接距阵*/
 int vex_num;  /*顶点数*/
}Graph;

Graph g; /*全局变量*/

/*构造集合*/
typedef struct collention{
 
    int vexs[MAX_VEX_NUM];
 int num;  /*集合中间的结点数*/

}Vexset;

Vexset vexset[MAX_VEX_NUM];

int flag[MAX_VEX_NUM];/*标志结点是否被添加到集合中*/

/*初始化标志位*/
void initflag(Graph *g){
 int i;
    for(i=0;i<g->vex_num;i++){
     flag[i]=0;
 }
}

/*添加结点到集合中*/
void addToSet(int i,Vexset *s){
    s->vexs[s->num]=i;
 s->num++;
}

void swap(int *i,int *j){
    int temp;
 temp=*i;
 *i=*j;
 *j=temp;
}

/*对集合中的元素进行排序*/
/*采用冒泡法*/
void sortSet(Vexset *s){
   int i;
   int j;
  
   for(i=0;i<s->num;i++){
       for(j=0;j<i;j++){
     if(s->vexs[j]>s->vexs[j+1]){
               swap(&(s->vexs[j]),&(s->vexs[j+1]));
     }
    }
   }
}


/*判断两个集合是否相等*/
int judgeEquals(Vexset *s1,Vexset *s2){
 
 int k;
 int result=1;

 /*先判断集合个数是否一样*/
 if(s1->num!=s2->num){
     result=0;
 }
 else{
  /*再判断相同位置上的元素是否相等*/
  for(k=0;k<s1->num;k++){
            if(s1->vexs[k]!=s2->vexs[k]){
        result=0;
   }
  }
 }
 return result;

}

/*-----初始化图------*/
void initGraph(Graph *g){
 int i;
 int j;
    printf("请输入图的结点数:");
 scanf("%d",&g->vex_num);
    printf("说明:请输入邻接矩阵,只能输0,1/n");
 printf("      由于是简单有向图,所以矩阵对角线上只能是0/n");
 printf("      而且邻接矩阵都只能有0,1构成的/n");

    for(i=0;i<g->vex_num;i++){
  for(j=0;j<g->vex_num;j++){
   if(i==j){
       g->arcs[i][j]=0; /*简单图不存在环*/
   }
   else{
    printf("请输入邻接矩阵坐标为(%d,%d):",i,j);
    scanf("%d",&g->arcs[i][j]);
   }
  }
 }

}

/*测试输入的值*/
void printMatrix(Graph *g){
 int i; /*计数器*/
 int j; /*计数器*/
   
 
    for(i=0;i<g->vex_num;i++){
  for(j=0;j<g->vex_num;j++){
      printf("%d   ",g->arcs[i][j]);
  }
  printf("/n");
 }

}

/*
   获得可达矩阵
   可达矩阵:若i与j之间存在通路,则A[i,j]为1,否则为0;
   若邻接矩阵是N*N的,则进行N次叠代
   其中:
   A0[i,j]表示邻接矩阵
   Ak[i,j]表示k次叠代后的A[i,j]的值
   Ak[i,j]=Ak-1[i,j]||(Ak-1[i,k]&&Ak-1[k,j])
*/
void getRecMatrix(Graph *g){
    int vex_num = g->vex_num;
    int k;
 int i;
 int j;

 for(k=0;k<vex_num;k++){
     for(i=0;i<vex_num;i++)
   for(j=0;j<vex_num;j++){
    if(i!=j){
     g->arcs[i][j] = g->arcs[i][j]|(g->arcs[i][k]&g->arcs[k][j]);
                }
   }
 }

}

/*
   判断两个结点之间是否连通
*/
int isConnect(int i,int j,Graph *g){
     return g->arcs[i][j];
}


void main(){
 int i;
 int j;
 int k;/*计数器*/
 int canadd;/*控制是否能添加到集合中*/
 int canprint;/*控制能否打印*/
    initGraph(&g);
 printf("该图的邻接矩阵为:/n");
 printMatrix(&g);
 printf("该图的可达矩阵为:/n");
    getRecMatrix(&g);
 printMatrix(&g);

    /*
    放入集合中的点就表示都是单连通的,
    即任意的i,j属于集合,若<i,j>不属于集合则,<j,i>属于集合
       做贪心搜索,发现与集合中的任意点都单连通的点就放入集合中
    在将该点从原来的图中逻辑删除,即将flag[i]设为1
    */
    for(i=0;i<g.vex_num;i++){
  initflag(&g);
     addToSet(i,&vexset[i]);
  flag[i]=1;
  for(j=0;j<g.vex_num;j++){
   if(flag[j]==0){
    canadd=1;
    for(k=0;k<vexset[i].num;k++){
     if(!isConnect(j,vexset[i].vexs[k],&g)&&!isConnect(vexset[i].vexs[k],j,&g)){
      canadd=0;/*表示不满足添加到集合的条件*/
     }
    }
    if(canadd==1){
        addToSet(j,&vexset[i]);
        flag[j]=1;
    }
   }
  }
 }
    printf("连通分支有:/n");
/*
 for(i=0;i<g.vex_num;i++){
  
  printf("(");
  for(j=0;j<vexset[i].num;j++){
   printf("%d,",vexset[i].vexs[j]);
  }
  printf(")/n");
 }
 printf("-------------------/n");
*/ 
 for(i=0;i<g.vex_num;i++){
  sortSet(&vexset[i]);
  canprint=1;
  for(k=0;k<i;k++){
   if(judgeEquals(&vexset[k],&vexset[i])){
               // printf("sadffsd/n");
     canprint=0;
   }
        }
        if(canprint){
   printf("(");
   for(j=0;j<vexset[i].num;j++){
    printf("%d,",vexset[i].vexs[j]);
   }
   printf(")/n");
  }
 }
 
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值