//这段代码还没有优化,第一个就是 在kruskal方法中的iswrong可以有两个地方改进
//一个是不使用 int[][] 而使用 map
//第二个就是 加进 wrongarr时可以使用 位运算来解决 (可以按这个思路去研究,本人还没有试过)
//isok() 可以使用位 运算来解决 假设有三个点 则 000 添加一个点 001 再添加 101 ... 根据他们的位置就可以判断出来了#include
#include
#define TITLE_T cout << "###############################" << endl;
#define TITLE_I cout << " 无向图转换成最小生成树" << endl;
using namespace std;
struct Edge {
int fr;
int to;
int value;
void copy(struct Edge *p)
{
this->fr = p->fr;
this->to = p->to;
this->value = p->value;
}
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////
class AdjacencyMatrix
{
public:
AdjacencyMatrix(int cn, int en);
~AdjacencyMatrix();
inline int setvalue(int pref, int next, int value);
int check() const;
int convert_prim(int logflag = 0);
int convert_kruskal(struct Edge *p_e, int logflag = 1);
void print_m() const;
void print_t() const;
private:
int citynum;
int edgenum;
int **matrix;
struct Edge *s_edge;
int iswrong(int ** wrongarr, struct Edge * p_e, int index); //kruskal
int isok(int *okarr, int fr, int to); //kruskal
};
AdjacencyMatrix::AdjacencyMatrix(int cn, int en)
:citynum(cn), edgenum(en)
{
int ** temp = new int*[cn];
for(int i = 0; i < cn; i++)
{
temp[i] = new int[cn];
}
for(int j = 0; j < cn; j++)
{
for(int k = 0; k < cn; k++)
{
if( j == k )
temp[j][j] = 0;
else
temp[j][k] = -1;
}
}
matrix = temp;
s_edge = NULL;
}
inline int AdjacencyMatrix::setvalue(int pref, int next, int value)
{
if( value <= 0 || pref >= citynum || next >= citynum || pref == next || *(*(matrix+pref)+next) > 0 )
return 0;
matrix[pref][next] = value;
matrix[next][pref] = value;
return value;
}
AdjacencyMatrix::~AdjacencyMatrix()
{
for(int i = 0; i < citynum; i++)
delete[] matrix[i];
delete[] matrix;
if( s_edge )
delete[] s_edge;
}
void AdjacencyMatrix::print_m() const
{
cout << "AdjacencyMatrix Info:/n";
for(int i = 0; i < citynum; i++)
{
for(int j = 0; j < citynum; j++)
cout << matrix[i][j] << "/t";
cout << endl;
}
}
void AdjacencyMatrix::print_t() const
{
if( s_edge )
{
cout << "min tree Info:/n";
for(int i = 0; i < citynum-1; i++)
{
char c = 'a';
printf("%c-%c:%d/n", c+s_edge[i].fr, c+s_edge[i].to, s_edge[i].value);
}
}//if s_edge
}
int AdjacencyMatrix::check() const
{
for(int i = 0; i < citynum; i++)
{
int sum = 0;
for(int j = 0; j < citynum; j++)
sum += matrix[i][j];
if( sum == -1*(citynum-1) )
return 0;
}
return 1;
}
int AdjacencyMatrix::convert_prim(int logflag)
{
(logflag) ? cout << "==================prim info==================/n" : cout <<"";
int *arr = new int[citynum];
int *leftarr = new int[citynum-1];
s_edge = new struct Edge[citynum-1];
cout << "init" << endl;
(logflag) ? cout << "leftarr = {" : cout << "";
for(int i=1; i < citynum; i++){
leftarr[i-1] = i;
(logflag) ? printf("%c,", 'a'+i) : printf("");
}
(logflag) ? cout << "}/n" : cout << "";
arr[0] = 0;
(logflag) ? cout << "arr = {a}/n" : cout << "";
int temp_to = 0;
for(int len = 1; len < citynum; len++)
{
struct Edge min = {-1, -1, 0};
for(int fr=0; fr < len; fr++)
{
int k = arr[fr];
for(int to=0; to < citynum-len; to++)
{
int v = leftarr[to];
if( matrix[k][v] == -1 || matrix[k][v] == 0 )
{
continue;
}
else
{
if( min.fr == -1 )
{
cout << "changed1! fr:" << k << " to:" << v << " v:" << matrix[k][v] << endl;
min.fr = k;
min.to = v;
min.value = matrix[k][v];
temp_to = to;
}
else
{
if( min.value > matrix[k][v])
{
cout << "changed2 fr:" << k << " to:" << v << " v:" << matrix[k][v] << endl;
min.fr = k;
min.to = v;
min.value = matrix[k][v];
temp_to = to;
}
}
}
}//for to
}//for fr
if( min.fr == -1 || min.to == -1 || min.value == 0 )
{
cout << "min error" << endl;
return 0;
}
cout << min.fr << " " << min.to << " " << min.value << endl;
s_edge[len-1].fr = min.fr;
s_edge[len-1].to = min.to;
s_edge[len-1].value = min.value;
arr[len] = min.to;
(logflag) ? printf("arr add[len]:%c/n", arr[len]+'a') : printf("");
for(int temp = temp_to+1; temp < citynum-len; temp++)
leftarr[temp-1] = leftarr[temp];
if( logflag )
{
cout << "leftarr = {";
for(int test=0; test < citynum-len-1; test++)
printf("%c,", 'a'+leftarr[test]);
cout << "}/n";
}
}//len
(logflag) ? cout << "==============================================/n" : cout << "";
delete[] arr;
delete[] leftarr;
return 1;
}
int AdjacencyMatrix::iswrong(int ** wrongarr, struct Edge * p_e, int index)
{
int smfr = p_e[index].fr;
int smto = p_e[index].to;
if( wrongarr[smfr][smto] == 1 )
return 1;
for(int i = 0; i < index; i++)
{
if( p_e[i].fr == smfr )
{
int min = smto;
int max = p_e[i].to;
if( p_e[i].to < smto ) {
min = p_e[i].to;
max = smto;
}
wrongarr[min][max] = 1;
cout << " wrong{} add:(" << min << ", " << max << ")/n";
}
else if( p_e[i].fr == smto )
{
wrongarr[smfr][p_e[i].to] = 1;
cout << " wrong{} add:(" << smfr << ", " << p_e[i].to << ")/n";
}
else if( p_e[i].to = smfr )
{
wrongarr[p_e[i].fr][smto] = 1;
cout << " wrong{} add:(" << p_e[i].fr << ", " << smto << ")/n";
}
else if( p_e[i].to == smto )
{
int min = smfr;
int max = p_e[i].fr;
if( p_e[i].fr < smfr ) {
min = p_e[i].fr;
max = smfr;
}
wrongarr[min][max] = 1;
cout << " wrong{} add:(" << min << ", " << max << ")/n";
}
}
return 0;
}
int AdjacencyMatrix::isok(int * okarr, int fr, int to)
{
if( okarr[fr] == 0 )
okarr[fr] = 1;
if( okarr[to] == 0)
okarr[to] = 1;
int sum = 0;
for(int i = 0; i < citynum; i++)
sum += okarr[i];
return (sum == citynum) ? 1 : 0;
}
int AdjacencyMatrix::convert_kruskal(struct Edge *p_e, int logflag)
{
cout << "================kruskal=================/n";
int *okarr = new int[citynum];
int ** wrongarr = new int*[citynum];
for(int i = 0; i < citynum; i++)
{
wrongarr[i] = new int[citynum];
okarr[i] = 0;
for(int j = 0; j < citynum; j++)
wrongarr[i][j] = 0;
}
s_edge = new struct Edge[citynum-1];
int index = 0;
for(int k = 0; k < edgenum; k++)
{
cout << "kruskal index:" << k << endl;
if( !iswrong(wrongarr, p_e, k) )
{
//s_edge[index].copy(p_e+j);
s_edge[index].fr = p_e[k].fr;
s_edge[index].to = p_e[k].to;
s_edge[index].value = p_e[k].value;
index++;
if( isok(okarr, p_e[k].fr, p_e[k].to) )
{
delete[] okarr;
for(int d_i = 0; d_i < citynum; d_i++)
delete[] wrongarr[d_i];
delete[] wrongarr;
cout << "=============================================/n";
return 1; //ok
}
}
}
delete[] okarr;
for(int d_i = 0; d_i < citynum; d_i++)
delete[] wrongarr[d_i];
delete[] wrongarr;
cout << "=============================================/n";
return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//return arr[2]
int * input()
{
int *arr = new int[2];
while(1)
{
cout << "please input city num:";
scanf("%d", &arr[0]);
if( arr[0] > 0 )
break;
cout << "input error" << endl;
//clear stdin cache
while(cin.get() != '/n')
continue;
}
cout << "the city name are:";
for(int i = 0; i < arr[0]; i++)
{
char c = 'a'+i;
cout << c << " ";
}
int limit1 = arr[0] - 1;
int limit2 = (1+arr[0]-1)*(arr[0]-1)/2;
while(1)
{
cout << "/nplease input edge num[" << limit1 << ", " << limit2 << "]:";
scanf("%d", &arr[1]);
if( arr[1] <= limit2 && arr[1] >= limit1 )
break;
cout << "input error" << endl;
//clear stdin cache
while(cin.get() != '/n')
continue;
}
return arr;
}
void q_sort(struct Edge *numbers, int left, int right)
{
struct Edge pivot;
pivot.copy(numbers+left);
int t_left = left;
int t_right = right;
while (left < right)
{
while(pivot.value <= numbers[right].value && left < right)
right--;
if (left != right) {
//swap(numbers+left, numbers+right);
numbers[left].copy(numbers+right);
left++;
}
while(pivot.value >= numbers[left].value && left < right)
left++;
if (left != right) {
//swap(numbers+left, numbers+right);
numbers[right].copy(numbers+left);
right--;
}
}//while when the left == right break
numbers[left].copy(&pivot); //there is a effect of swap
if (t_left < left)
q_sort(numbers, t_left, left-1);
if (right < t_right)
q_sort(numbers, right+1, t_right);
}
void quicksort(struct Edge *p_e, int array_size)
{
q_sort(p_e, 0, array_size-1);
}
struct Edge * setedgevalue(AdjacencyMatrix *am, int edgenum, char c)
{
struct Edge *p_e;
if( c == 'k' )
p_e = new struct Edge[edgenum];
int i = 1;
while( i <= edgenum )
{
cout << "please input edge[" << i << "] value:(eg: a b 12)" << endl;
char c1, c2;
int v;
cin >> c1 >> c2 >> v;
if( am->setvalue(c1-'a', c2-'a', v) )
{
if( c == 'k' )
{
p_e[i-1].fr = c1-'a';
p_e[i-1].to = c2-'a';
p_e[i-1].value = v;
}
i++;
}
else
cout << "input wrong!" << endl;
while(cin.get() != '/n')
continue;
}//while i
if( c == 'k' ) {
quicksort(p_e, edgenum);
return p_e;
}
return NULL;
}
int main(int argc, char *argv[])
{
TITLE_T;
TITLE_I;
TITLE_T;
int * arr = input();
int citynum = arr[0];
int edgenum = arr[1];
delete[] arr;
AdjacencyMatrix *am = new AdjacencyMatrix(citynum, edgenum);
char c;
while( 1 )
{
cout << "/nuse prim:input p or use kruskal:input k!/n";
while(cin.get() != '/n')
continue;
scanf("%c", &c);
if( c == 'p' || c == 'k' )
break;
cout << "input wrong!/n";
}
struct Edge *p_e = setedgevalue(am, edgenum, c);
if( !am->check() ) {
cout << "输入的不连通图" << endl;
return 1;
}
am->print_m();
if( !p_e )
am->convert_prim(1);
else
am->convert_kruskal(p_e, 1);
am->print_t();
system("PAUSE");
return 1;
}