最小圈基问题

来源:互联网 发布:搜索下载 python 实现 编辑:程序博客网 时间:2024/04/29 23:41

算法分析实验,写的有点乱,保存备用,同时供大家参考,写的不是很好,如有问题可提出交流和修改!

#include<iostream>#include<vector>#include<set>using namespace std;static int temp = 0;//在找圈方法中用于圈个数的计数class Circle{public:Circle(){this->vertexNum = 0;this->circleWeight = 0;vertex = new pair<int, int>[10];circleEdge.resize(10);}int getCircleWeight()   //计算并返回圈的权{for (int i = 0; i < vertexNum; i++){circleWeight += circleEdge[i];}return circleWeight;}public:int vertexNum;                  //圈的顶点数vector<int> circleEdge;         //二维数组存储边的权int circleWeight;               //圈的权值pair<int, int> *vertex;         //存储圈的边的坐标};class MatrixGraphic{public:MatrixGraphic(){this->vertexNum = 0;this->edgeNum = 0;this->graphicWeight = 0;this->circleNum = 0;}MatrixGraphic(int verNumber, int edgNumber){circle = new Circle[10];vector<vector<int>> a(verNumber);this->vertexNum = verNumber;this->edgeNum = edgNumber;mixCircleNum = (edgeNum + 1) - vertexNum;edge = a;for (int i = 0; i <vertexNum; i++)edge[i].resize(vertexNum);    //初始化邻接矩阵的大小}/*输入整个图*/void cinGraphic();/*找出所有圈并对其按照权的大小进行升序排序*/void fundCircle(int num1, int num2,int num3,vector<pair<int,int> > b);/*是否能组成圈*/bool isCircle(int num,vector<pair<int, int> > b);/*找最小圈基*/int fundMinCircle();/*判断一个圈是否是圈基中的线性组合*///void isCombin(int n);/*是否停止向圈基中继续加圈*///bool isStop(int n);public:int vertexNum; //图的顶点数int edgeNum; //图的边数int graphicWeight; //图的权值vector<vector<int>> edge; //二维数组存储边的权pair<int,int> vertex[20];    //存储边的坐标Circle* circle;              //图中各圈int circleNum;               //计数器,计算圈的个数int mixCircleNum;            //最小圈基的范围};void MatrixGraphic::cinGraphic(){int num = 0;cout << "请以"<< vertexNum <<"*"<< vertexNum <<"的邻接矩阵的形式输入图:" << endl;for (int i = 0; i < vertexNum; i++)for (int j = 0; j < vertexNum; j++){int n;cin >> n;edge[i][j] = n;}/*存储图的边的坐标*/for (int i = 0; i < vertexNum; i++)for (int j = i; j < vertexNum; j++){if (edge[i][j] != 0){vertex[num].first = i;vertex[num].second = j;num++;}}}/*用组合算法找出n个顶点的所有组合(不考虑位置)  num1为图的顶点个数,num2为组合的顶点个数,b为所有组合构成的集合*/void MatrixGraphic::fundCircle(int num1, int num2,int num3, vector<pair<int,int> > b){for (int i = num1; i >= num2; i--) {/*找出组合*/b[num2 - 1] = vertex[i - 1];if (num2 > 1){fundCircle(i - 1, num2 - 1, num3, b);}else {/*如果组合能构成圈,将其放到circle中*/if (isCircle(num3, b)) {for (int i = b.size() - 1; i >= 0; i--){circle[temp].vertex[i] = b[i]; //将顶点赋值给对应的圈的顶点circle[temp].circleEdge[i] = edge[b[i].first][b[i].second];}circleNum += 1;circle[temp].vertexNum = b.size();++temp;}}}}/*判断是否构成圈思路:(1)n条边能组合成圈的顶点只有n个(2)所有边的坐标点的集合都是成对出现的,如(01 03 12 23中0 1 2 3都是成对出现的)(3)*/bool MatrixGraphic::isCircle(int num, vector<pair<int, int> > b){vector<int> ver;set<int>s0;set<int>s1;set<int>s2;int n = 0;for (int i = 0; i < b.size(); i++){s0.insert(b[i].first);}for (int i = 0; i < b.size(); i++){s1.insert(b[i].second);}for (int i = 0; i < b.size(); i++){ver.push_back(b[i].first);ver.push_back(b[i].second);s2.insert(b[i].first);s2.insert(b[i].second);}/*n条边能组合成圈的顶点只有n个,且都是成对出现的(有且只有两个)*/for (int i = 0; i < b.size() * 2; i++){for (int j = 0; j < b.size() * 2; j++){if (ver[i] == ver[j])n += 1;}if (n > 2)return false;else{n = 0;}}if (s2.size() == num && s0.size() == (num - 1) && s1.size() == (num - 1) )return true;elsereturn false;}/*找最小圈基的思路:对排好序的圈挨个放进圈基,如果圈是圈基的线性组合(即圈的所有边在圈基中都可以找到),删掉直到圈基中圈的个数满足要求停止加圈*/int MatrixGraphic::fundMinCircle(){static int temp1 = 2;int minCircle = 0;  //最小圈基的权set<pair<int,int> >MySet;Circle *Mycircle = new Circle[mixCircleNum];for (int i = 0; i < circleNum; i++){if (i < 2){Mycircle[i] = circle[i];}else{/*先把所有的边放到集合set中*/for (int a = 0; a < i; a++){for (int b = 0; b < circle[a].vertexNum; b++){MySet.insert(Mycircle[a].vertex[b]);}}temp = 0;for (int j = 0; j < circle[i].vertexNum; j++)//检验第i是否是组合成的,分别扫描它的所有顶点{if (MySet.find(circle[i].vertex[j])!=MySet.end()){temp += 1;}}if (temp != circle[i].vertexNum){Mycircle[temp1] = circle[i];temp1++;}if (temp1 == (mixCircleNum))break;MySet.clear();}}for (int i = 0; i < mixCircleNum; i++){minCircle += Mycircle[i].circleWeight;}/*输出最小圈基*/cout <<endl<< "最小圈基:" << endl;for (int i = 0; i < mixCircleNum; i++){for (int j = 0; j < Mycircle[i].vertexNum; j++){cout << Mycircle[i].vertex[j].first << Mycircle[i].vertex[j].second << " ";}cout << endl;}return minCircle;}int main(){int e, v;                                     //存储图的顶点和边cout << "请输入图的顶点和边数:" << endl;cin >> e >> v;MatrixGraphic MyGraphic(e,v);                 //定义一个图对象MyGraphic.cinGraphic();                       //调用cinGraphic()方法,以邻接矩阵的形式输入整个图//找到所有的圈/*找圈的思路:(1)3个或3个以上的顶点可构成圈,找出可以构成圈的所有可能的顶点组合(2)从找出的组合中再筛选出真正能构成圈的*/for (int i = 3; i <= v; i++){vector<pair<int, int> > b(i);MyGraphic.fundCircle(v, i,i, b);//fundCircle方法用到了排列组合}cout << "输出图中所有圈的权:" << endl;for (int i = 0; i < MyGraphic.circleNum; i++){MyGraphic.circle[i].getCircleWeight();  //计算圈的权cout << MyGraphic.circle[i].circleWeight << "  ";}/*对所有圈按照升序排列*/Circle MyCircl;for (int i = 0; i < MyGraphic.circleNum - 1; i++){for (int j = i+1; j < MyGraphic.circleNum ; j++)if (MyGraphic.circle[i].circleWeight > MyGraphic.circle[j].circleWeight){MyCircl = MyGraphic.circle[i];MyGraphic.circle[i] = MyGraphic.circle[j];MyGraphic.circle[j] = MyCircl;}}cout << endl;cout << "排序后的圈的权:" << endl;for (int i = 0; i < MyGraphic.circleNum; i++){//MyGraphic.circle[i].getCircleWeight();cout << MyGraphic.circle[i].circleWeight << "  ";}cout<<endl<<"最小圈基的权:"<<MyGraphic.fundMinCircle()<<endl;//调用fundMinCircle()方法,输出最小圈基和它的权return 0;}

0 0
原创粉丝点击