数据结构_队列应用举例_划分子集问题

原帖 http://luojilie.blog.163.com/blog/static/191826963201176111715304/

Description

       已知集合A={a1,a2,……an},及集合上的关系R={ (ai,aj) | ai,aj?A, i?j},其中(ai,aj)表示ai与aj间存在冲突关系。要求将A划分成互不相交的子集A1,A2,……Ak,(k?n),使任何子集中的元素均无冲突关系,同时要求分子集个数尽可能少   

Sample Input

            
 A={1,2,3,4,5,6,7,8,9}

      R={ (2,8), (9,4), (2,9), (2,1), (2,5), (6,2), (5,9),(5,6), (5,4), (7,5), (7,6), (3,7), (6,3) }

Sample Output     

      A1={ 1,3,4,8 }

      A2={ 2,7 }

      A3={ 5 }

             A4={ 6,9 }

  (可行的子集划分)

Hint

算法思想:

利用循环筛选。从第一个元素开始,凡与第一个元素无冲突的元素划归一组;再将剩下的元素重新找出互不冲突的划归第二组;直到所有元素进组
所用数据结构
冲突关系矩阵
r[i][j]=1,  i,j有冲突
r[i][j]=0,  i,j无冲突
循环队列cq[n]
数组result[n]存放每个元素分组号
工作数组newr[n]

工作过程:
初始状态:A中元素放于cq中,result和newr数组清零,组号group=1
第一个元素出队,将r矩阵中第一行“1”拷入newr中对应位置,这样,凡与第一个元素有冲突的元素在newr中对应位置处均为“1”,下一个元素出队
若其在newr中对应位置为“1”,有冲突,重新插入cq队尾,参加下一次分组
若其在newr中对应位置为“0”, 无冲突,可划归本组;再将r矩阵中该元素对应行中的“1”拷入newr中
如此反复,直到9个元素依次出队,由newr中为“0”的单元对应的元素构成第1组,将组号group值“1”写入result对应单元中
令group=2,newr清零,对cq中元素重复上述操作,直到cq中front==rear,即队空,运算结束

 


《数据结构_队列应用举例_划分子集问题》  

//Author: essence_of_ACMER 
//Time:2011.8.6
//Theme:Array_Subset

 #include <iostream>
using namespace std;
#define N 9
int front=0,rear=0,group=0;

void division(int r[][N],int n,int cq[ ],int newer[ ],int result[ ])  //主要函数
{
    int k,pre,i;
    for(k=0;k<n;k++)
       {cq[k]=k+1;newer[k]=0;}
    front=n-1;
    rear=n-1;
    group=1;
    pre=0;

    do{front=(front+1)%n;
       i=cq[front];

       if(i<pre)    //分组
          {
           group++;
           result[i-1]=group;
           for(k=0;k<n;k++) newer[k]=r[i-1][k];
          }

 

        else if(newer[i-1]!=0)   //用冲突就放到下一组
            {
                rear=(rear+1)%n;
                cq[rear]=i;
            }


        else        //无冲突就放入该组
            {
              result[i-1]=group;
              for(k=0;k<n;k++)
                 newer[k]+=r[i-1][k];
            }

        pre=i;    //pre用来判断一轮是否搞完

    }while(front!=rear);
}


int main()
{ //system("pause");
 int a[N]={0},r[N][N]={0,1,0,0,0,0,0,0,0,
                  1,0,0,0,1,1,0,1,1,
                  0,0,0,0,0,1,1,0,0,
                  0,0,0,0,1,0,0,0,1,
                  0,1,0,1,0,1,1,0,1,
                  0,1,1,0,1,0,1,0,0,
                  0,0,1,0,1,1,0,0,0,
                  0,1,0,0,0,0,0,0,0,
                  0,1,0,1,1,0,0,0,0};
 int newer[N]={0},result[N]={0};

division(r,N,a,newer,result);    //函数调用
 //system("pause");
for(int k=0;k<N;k++)
a[k]=k+1;
//system("pause");
for(k=1;k<=group;k++)    //输出各组数据
{
       cout<<"Group "<<k<<":"<<endl;//system("pause");
   for(int j=0;j<N;j++)
   { if(result[j]==k) cout<<a[j]<<"  ";}
   cout<<endl;
}
return (0);
}
    原文作者:舞伴问题
    原文地址: https://blog.csdn.net/xingkong_678/article/details/38665493
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞