图的着色,贪心算法(文件读取)
题目描述:给定无向连通图G=(V, E),求图G的最小着色数k,使得用k种颜色对G中的顶点着色,可使任意两个相邻顶点着色不同。
例如,下图可以只用两种颜色着色,将顶点1、3和4着成一种颜色,将顶点2和顶点5着成另外一种颜色。
功能要求及说明:
(1)将上图存入文件,运行时从文件读取数据;
(2)输出所求最小着色数以及着某个颜色的所有顶点;
(3)采用模块化设计。
主要算法:贪心算法
此设计的算法描述:以任意顶点作为开始顶点,依次考察图中的未被着色的每个顶点。如果一个顶点可以用颜色1着色,换言之,该顶点的邻接点都还未被着色,则用颜色1为该顶点着色,当没有顶点能以这种颜色着色时,选择颜色2和一个未被着色的顶点作为开始顶点,用第二种颜色为尽可能多的顶点着色,如果还有未着色的顶点,则选取颜色3并为尽可能多的顶点着色,依此类推。
贪心算法描述:贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解 。
#include<iostream>
#include<fstream>
#include<sstream>
#include<vector>
using namespace std;
//判断当前的顶点的邻接顶点是否与当前的着色是否冲突
bool IsOk( vector<vector<int> > num, int *vertex, int node, int color, int number)
{
for (int i = 0; i < number; i++)
//邻接点且着色冲突,且冲突点不是该点本身
if (num[node][i] == 1 && vertex[i] == color && node != i)
return false;
return true;
}
//从文件中读取邻接矩阵(传入文件的绝对地址)
vector<vector<int> > readTxt(string path)
{
ifstream f;
//打开文件
f.open(path);
//文件地址
string str;
//用来存储邻接矩阵的动态二维向量
vector<vector<int> > num;
//按行读取文件
while(getline(f, str))
{
//从字符串str中读取字符
istringstream input(str);
//临时的一维向量
vector<int> tmp;
int a;
//将整数字符保存的临时一维向量
while(input >> a)
tmp.push_back(a);
//将一维向量保存二维向量中
num.push_back(tmp);
}
cout<<"邻接矩阵为:"<<endl;
for (int i = 0; i < num.size(); ++i)
{
for (int j = 0; j < num[i].size(); ++j)
{
cout << num[i][j] << " ";
}
cout << endl;
}
return num;
}
/*
*输入一个邻接矩阵,输出这个邻接矩阵对应的
*图的最少着色数以及每一个颜色下的顶点
*主要采用了贪婪算法:算法描述如下
*以任意顶点作为开始顶点,依次考察图中的未被着色的每个顶点。
*如果一个顶点可以用颜色1着色,换言之,该顶点的邻接点都还未被着色,
*则用颜色1为该顶点着色,当没有顶点能以这种颜色着色时,
*选择颜色2和一个未被着色的顶点作为开始顶点,
*用第二种颜色为尽可能多的顶点着色,如果还有未着色的顶点,
*则选取颜色3并为尽可能多的顶点着色,依此类推。
*/
void minColor(vector<vector<int> > N){
//存储邻接矩阵的二维向量
vector<vector<int> > num = N;
//顶点数
int number = num.size();
//存储顶点颜色
int *vertex = new int[number];
//申请内存及初始化顶点颜色
for (int i = 0; i < number; i++)
{
vertex[i] = 0;
}
//置首节点颜色为1
vertex[0] = 1;
//标志位,是否有节点未被染色
int flag = 1;
//颜色数量
int color = 0;
//每循环一次用颜色color给尽可能多的结点染色
while (flag)
{
color++;
for (int i = 1; i < number; i++)
{
//已着色
if (vertex[i] != 0)
continue;
//未着色
else
{
if (IsOk(num, vertex, i, color, number))
vertex[i] = color;
}
}
int k = 0;
for (k = 1; k < number; k++)
{
//有顶点未被着色
if (vertex[k] == 0)
break;
}
if (k == number)
flag = 0;
}
cout <<"图的最少着色数是:"<<color<< "\n着色情况如下:" << endl;
for (int i = 0; i < color; i++){
cout <<i+1<< "号颜色着色的顶点是:";
for(int j = 0;j<number;j++){
if(vertex[j] == i+1)
cout<<j+1<<" ";
}
cout<<endl;
}
}
int main()
{
//二维邻接矩阵向量
vector<vector<int> > num;
while(true){
cout<<"*********************欢迎来到图的着色系统**********************\n"
<<"* *\n"
<<"* 1-读取邻接矩阵 *\n"
<<"* *\n"
<<"* 2-打印图的最少着色数以及着色情况 *\n"
<<"* *\n"
<<"* 0-退出系统 *\n"
<<"* *\n"
<<"***************************************************************\n";
cout<<"请输入选项:";
char a;
string path;
cin>>a;
switch(a){
case '1':
cout<<"输入图表的绝对地址:";
cin>>path;
num = readTxt(path);
//任意键按下后 清屏
system("pause");
system("cls");
break;
case '2':
minColor(num);
system("pause");
system("cls");
break;
case '0':
exit(1);
}
}
return 0;
}